Commit 4537623d12fb7372262267be5d6ec3b41f3f476c

Authored by Dmitriy Zaporozhets
2 parents c7e490eb 1a83fea7

Merge branch 'master' into karlhungus-mr-on-fork

Conflicts:
	app/contexts/filter_context.rb
	app/contexts/search_context.rb
	app/models/merge_request.rb
	app/models/note.rb
	app/views/shared/_merge_requests.html.haml
	spec/controllers/commit_controller_spec.rb
	spec/services/notification_service_spec.rb
Showing 165 changed files with 1334 additions and 909 deletions   Show diff stats
@@ -30,3 +30,5 @@ vendor/bundle/* @@ -30,3 +30,5 @@ vendor/bundle/*
30 rails_best_practices_output.html 30 rails_best_practices_output.html
31 doc/code/* 31 doc/code/*
32 .secret 32 .secret
  33 +*.log
  34 +public/uploads.*
CONTRIBUTING.md
@@ -2,6 +2,12 @@ @@ -2,6 +2,12 @@
2 2
3 This guide details how to use issues and pull requests to improve GitLab. 3 This guide details how to use issues and pull requests to improve GitLab.
4 4
  5 +- [Closing policy for issues and pull requests](#closing-policy-for-issues-and-pull-requests)
  6 +- [Issue tracker](#issue-tracker)
  7 +- [Pull requests](#pull-requests)
  8 +
  9 +If you want to know how the GitLab team handles contributions have a look at [the GitLab contributing process](PROCESS.md).
  10 +
5 ## Closing policy for issues and pull requests 11 ## Closing policy for issues and pull requests
6 12
7 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. 13 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.
@@ -23,7 +23,7 @@ gem 'omniauth-github' @@ -23,7 +23,7 @@ gem 'omniauth-github'
23 23
24 # Extracting information from a git repository 24 # Extracting information from a git repository
25 # Provide access to Gitlab::Git library 25 # Provide access to Gitlab::Git library
26 -gem 'gitlab_git', '~> 1.4.1' 26 +gem "gitlab_git", "~> 2.0.0.pre"
27 27
28 # Ruby/Rack Git Smart-HTTP Server Handler 28 # Ruby/Rack Git Smart-HTTP Server Handler
29 gem 'gitlab-grack', '~> 1.0.1', require: 'grack' 29 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
@@ -176,7 +176,7 @@ GEM @@ -176,7 +176,7 @@ GEM
176 gitlab-pygments.rb (0.3.2) 176 gitlab-pygments.rb (0.3.2)
177 posix-spawn (~> 0.3.6) 177 posix-spawn (~> 0.3.6)
178 yajl-ruby (~> 1.1.0) 178 yajl-ruby (~> 1.1.0)
179 - gitlab_git (1.4.1) 179 + gitlab_git (2.0.0.pre)
180 activesupport (~> 3.2.13) 180 activesupport (~> 3.2.13)
181 github-linguist (~> 2.3.4) 181 github-linguist (~> 2.3.4)
182 gitlab-grit (~> 2.6.0) 182 gitlab-grit (~> 2.6.0)
@@ -275,7 +275,7 @@ GEM @@ -275,7 +275,7 @@ GEM
275 minitest (4.7.4) 275 minitest (4.7.4)
276 modernizr (2.6.2) 276 modernizr (2.6.2)
277 sprockets (~> 2.0) 277 sprockets (~> 2.0)
278 - multi_json (1.7.7) 278 + multi_json (1.7.8)
279 multi_xml (0.5.4) 279 multi_xml (0.5.4)
280 multipart-post (1.2.0) 280 multipart-post (1.2.0)
281 mysql2 (0.3.11) 281 mysql2 (0.3.11)
@@ -568,7 +568,7 @@ DEPENDENCIES @@ -568,7 +568,7 @@ DEPENDENCIES
568 gitlab-gollum-lib (~> 1.0.1) 568 gitlab-gollum-lib (~> 1.0.1)
569 gitlab-grack (~> 1.0.1) 569 gitlab-grack (~> 1.0.1)
570 gitlab-pygments.rb (~> 0.3.2) 570 gitlab-pygments.rb (~> 0.3.2)
571 - gitlab_git (~> 1.4.1) 571 + gitlab_git (~> 2.0.0.pre)
572 gitlab_meta (= 6.0) 572 gitlab_meta (= 6.0)
573 gitlab_omniauth-ldap (= 1.0.3) 573 gitlab_omniauth-ldap (= 1.0.3)
574 gon 574 gon
PROCESS.md 0 → 100644
@@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
  1 +# GitLab Contributing Process
  2 +
  3 +## Purpose of describing the contributing process
  4 +
  5 +Below we describe the contributing process for two reasons. Contributors know what to expect from maintainers (initial, response within xx days, friendly treatment, etc). And maintainers know what to expect from contributors (use latest version, confirm the issue is addressed, friendly treatment, etc).
  6 +
  7 +## How we handle issues
  8 +
  9 +The priority should be mentioning people that can help and assigning workflow labels. Workflow labels are purposely not very detailed since that would be hard to keep updated as you would need to reevaluate them after every comment. We optionally use functional labels on demand when want to group related issues to get an overview (for example all issues related to RVM, to tackle them in one go) and to add details to the issue.
  10 +
  11 +If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
  12 +
  13 +Priority (from high to low):
  14 +
  15 +1. Mentioning people (very important)
  16 +2. Workflow labels
  17 +3. Functional labels (less important)
  18 +4. Assigning issues (optional)
  19 +
  20 +## Workflow labels
  21 +
  22 +- _Awaiting feedback_: Feedback pending from the reporter
  23 +- _Awaiting confirmation of fix_: The issue should already be solved in **master** (generally you can avoid this workflow item and just close the issue right away)
  24 +- _Attached PR_: There is a PR attached and the discussion should happen there
  25 + - We need to let issues stay in sync with the PR's. We can do this with a "Closing #XXXX" or "Fixes #XXXX" comment in the PR. We can't close the issue when there is a pull request because sometimes a PR is not good and we just close the PR, then the issue must stay.
  26 +- _Awaiting developer action/feedback_: Issue needs to be fixed or clarified by a developer
  27 +
  28 +## Functional labels
  29 +
  30 +These labels describe what development specialities are involved such as: PostgreSQL, UX, LDAP.
  31 +
  32 +## Label colors
  33 +- Light orange `#fef2c0`: workflow labels for issue team members (awaiting feedback, awaiting confirmation of fix)
  34 +- Bright orange `#eb6420`: workflow labels for core team members (attached PR, awaiting developer action/feedback)
  35 +- Light blue `#82C5FF`: functional labels
  36 +- Green labels `#009800`: issues that can generally be ignored. For example, issues given the following labels normally can be closed immediately:
  37 + - Feature request (see copy & paste response: [Feature requests](#feature-requests))
  38 + - Support (see copy & paste response: [Support requests and configuration questions](#support-requests-and-configuration-questions)
  39 +
  40 +## Common actions
  41 +
  42 +### Issue team
  43 +- Looks for issues without workflow labels and triages issue
  44 +- Monitors pull requests
  45 +- Closes invalid issues and pull requests with a comment (duplicates, [feature requests](#feature-requests), [fixed in newer version](#issue-fixed-in-newer-version), [issue report for old version](#issue-report-for-old-version), not a problem in GitLab, etc.)
  46 +- Assigns appropriate [labels](#how-we-handle-issues)
  47 +- Asks for feedback from issue reporter/pull request initiator ([invalid issue reports](#improperly-formatted-issue), [format code](#code-format), etc.)
  48 +- Asks for feedback from the relevant developer(s) based on the [list of members and their specialities](http://gitlab.org/team/)
  49 +- Monitors all issues/pull requests for feedback (but especially ones commented on since automatically watching them):
  50 +- Assigns issues to developers if they indicate they are fixing it
  51 +- Assigns pull requests to developers if they indicate they will take care of merge
  52 +- Closes issues with no feedback from the reporter for two weeks
  53 +- Closes stale pull requests
  54 +
  55 +### Development team
  56 +
  57 +- Responds to issues and pull requests the issue team mentions them in
  58 +- Monitors for new issues in _Awaiting developer action/feedback_ with no developer activity (once a week)
  59 +- Monitors for new pull requests (at least once a week)
  60 +- Manages their work queue by looking at issues and pull requests assigned to them
  61 +- Close fixed issues (via commit messages or manually)
  62 +- Codes [new features](http://feedback.gitlab.com/forums/176466-general/filters/top)!
  63 +- Response guidelines
  64 +- Be kind to people trying to contribute. Be aware that people can be a non-native or a native English speaker, they might not understand thing or they might be very sensitive to how your word things. Use emoji to express your feelings (hearth, star, smile, etc.). Some good tips about giving feedback to pull requests is in the [Thoughtbot code review guide](https://github.com/thoughtbot/guides/tree/master/code-review).
  65 +
  66 +## Copy & paste responses
  67 +
  68 +### Improperly formatted issue
  69 +
  70 +Thanks for the issue report. Please reformat your issue to conform to the issue tracker guidelines found in our \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#issue-tracker-guidelines).
  71 +
  72 +### Feature requests
  73 +
  74 +Thanks for your interest in GitLab. We don't use the GitHub issue tracker for feature requests. Please use http://feedback.gitlab.com/ for this purpose or create a pull request implementing this feature. Have a look at the \[contribution guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) for more information.
  75 +
  76 +### Issue report for old version
  77 +
  78 +Thanks for the issue report but we only support issues for the latest stable version of GitLab. I'm closing this issue but if you still experience this problem in the latest stable version, please open a new issue (but also reference the old issue(s)). Make sure to also include the necessary debugging information conforming to the issue tracker guidelines found in our \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#issue-tracker-guidelines).
  79 +
  80 +### Support requests and configuration questions
  81 +
  82 +Thanks for your interest in GitLab. We don't use the GitHub issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the unofficial #gitlab IRC channel on Freenode or the http://www.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) for more information.
  83 +
  84 +### Code format
  85 +
  86 +Please use ``` to format console output, logs, and code as it's very hard to read otherwise.
  87 +
  88 +### Issue fixed in newer version
  89 +
  90 +Thanks for the issue report. This issue has already been fixed in newer versions of GitLab. Due to the size of this project and our limited resources we are only able to support the latest stable release as outlined in our \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#issue-tracker). In order to get this bug fix and enjoy many new features please \[upgrade\]\(http://blog.gitlab.org/). If you still experience issues at that time please open a new issue following our issue tracker guidelines found in the \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#issue-tracker-guidelines).
  91 +
  92 +### Improperly formatted pull request
  93 +
  94 +Thanks for your interest in improving the GitLab codebase! Please update your pull request according to the \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#pull-request-guidelines).
  95 +
  96 +### Inactivity close of an issue
  97 +
  98 +It's been at least 2 weeks (and a new release) since we heard from you. I'm closing this issue but if you still experience this problem, please open a new issue (but also reference the old issue(s)). Make sure to also include the necessary debugging information conforming to the issue tracker guidelines found in our \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#issue-tracker-guidelines).
  99 +
  100 +### Inactivity close of a pull request
  101 +
  102 +This pull request has been closed because a request for more information has not been reacted to for more than 2 weeks. If you respond and conform to the pull request guidelines in our \[contributing guidelines\]\(https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md#pull-requests) we will reopen this pull request.
  103 +
@@ -147,6 +147,8 @@ or start each component separately @@ -147,6 +147,8 @@ or start each component separately
147 147
148 * [Mailing list](https://groups.google.com/forum/#!forum/gitlabhq) and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) are the best places to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and has resolved it. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix. 148 * [Mailing list](https://groups.google.com/forum/#!forum/gitlabhq) and [Stack Overflow](http://stackoverflow.com/questions/tagged/gitlab) are the best places to ask questions. For example you can use it if you have questions about: permission denied errors, invisible repos, can't clone/pull/push or with web hooks that don't fire. Please search for similar issues before posting your own, there's a good chance somebody else had the same issue you have now and has resolved it. There are a lot of helpful GitLab users there who may be able to help you quickly. If your particular issue turns out to be a bug, it will find its way from there to a fix.
149 149
  150 +* [Unofficial #gitlab IRC on Freenode](http://www.freenode.net/) is another way to get in touch with other GitLab users who may be able to help you.
  151 +
150 * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab. 152 * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
151 153
152 * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed. 154 * [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
app/assets/javascripts/behaviors/toggler_behavior.coffee
@@ -11,3 +11,7 @@ $ -> @@ -11,3 +11,7 @@ $ ->
11 container = $(".js-toggle-visibility-container") 11 container = $(".js-toggle-visibility-container")
12 container.toggleClass("hide") 12 container.toggleClass("hide")
13 e.preventDefault() 13 e.preventDefault()
  14 +
  15 + $("body").on "click", ".js-toggle-button", (e) ->
  16 + $(@).closest(".js-toggle-container").find(".js-toggle-content").toggle()
  17 + e.preventDefault()
app/assets/javascripts/branch-graph.js.coffee
@@ -62,22 +62,22 @@ class BranchGraph @@ -62,22 +62,22 @@ class BranchGraph
62 cuday = 0 62 cuday = 0
63 cumonth = "" 63 cumonth = ""
64 64
65 - r.rect(0, 0, 26, @barHeight).attr fill: "#222"  
66 - r.rect(26, 0, 20, @barHeight).attr fill: "#444" 65 + r.rect(0, 0, 40, @barHeight).attr fill: "#222"
  66 + r.rect(40, 0, 30, @barHeight).attr fill: "#444"
67 67
68 for day, mm in @days 68 for day, mm in @days
69 if cuday isnt day[0] 69 if cuday isnt day[0]
70 # Dates 70 # Dates
71 - r.text(36, @offsetY + @unitTime * mm, day[0]) 71 + r.text(55, @offsetY + @unitTime * mm, day[0])
72 .attr( 72 .attr(
73 font: "12px Monaco, monospace" 73 font: "12px Monaco, monospace"
74 - fill: "#DDD" 74 + fill: "#BBB"
75 ) 75 )
76 cuday = day[0] 76 cuday = day[0]
77 77
78 if cumonth isnt day[1] 78 if cumonth isnt day[1]
79 # Months 79 # Months
80 - r.text(13, @offsetY + @unitTime * mm, day[1]) 80 + r.text(20, @offsetY + @unitTime * mm, day[1])
81 .attr( 81 .attr(
82 font: "12px Monaco, monospace" 82 font: "12px Monaco, monospace"
83 fill: "#EEE" 83 fill: "#EEE"
app/assets/javascripts/dispatcher.js.coffee
@@ -39,7 +39,9 @@ class Dispatcher @@ -39,7 +39,9 @@ class Dispatcher
39 39
40 switch path.first() 40 switch path.first()
41 when 'admin' then new Admin() 41 when 'admin' then new Admin()
42 - when 'wikis' then new Wikis() 42 + when 'projects'
  43 + new Wikis() if path[1] == 'wikis'
  44 +
43 45
44 initSearch: -> 46 initSearch: ->
45 autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts') 47 autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts')
app/assets/javascripts/extensions/jquery.js.coffee
@@ -7,3 +7,7 @@ $.fn.enableButton = -> @@ -7,3 +7,7 @@ $.fn.enableButton = ->
7 $(@).removeAttr('disabled'). 7 $(@).removeAttr('disabled').
8 removeClass('disabled') 8 removeClass('disabled')
9 9
  10 +$.fn.disableButton = ->
  11 + $(@).attr('disabled', 'disabled').
  12 + addClass('disabled')
  13 +
app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -44,7 +44,7 @@ GitLab.GfmAutoComplete = @@ -44,7 +44,7 @@ GitLab.GfmAutoComplete =
44 tpl: @Issues.template 44 tpl: @Issues.template
45 callbacks: 45 callbacks:
46 before_save: (issues) -> 46 before_save: (issues) ->
47 - $.map issues, (i) -> id: i.id, title: i.title, search: "#{i.id} #{i.title}" 47 + $.map issues, (i) -> id: i.id, title: sanitize(i.title), search: "#{i.id} #{i.title}"
48 48
49 input.one "focus", => 49 input.one "focus", =>
50 $.getJSON(@dataSource).done (data) -> 50 $.getJSON(@dataSource).done (data) ->
app/assets/javascripts/main.js.coffee
@@ -119,7 +119,7 @@ $ -> @@ -119,7 +119,7 @@ $ ->
119 119
120 120
121 # Commit show suppressed diff 121 # Commit show suppressed diff
122 - $(".supp_diff_link").bind "click", -> 122 + $(".content").on "click", ".supp_diff_link", ->
123 $(@).next('table').show() 123 $(@).next('table').show()
124 $(@).remove() 124 $(@).remove()
125 125
app/assets/javascripts/merge_requests.js.coffee
@@ -22,12 +22,7 @@ class MergeRequest @@ -22,12 +22,7 @@ class MergeRequest
22 this.$('.show-all-commits').on 'click', => 22 this.$('.show-all-commits').on 'click', =>
23 this.showAllCommits() 23 this.showAllCommits()
24 24
25 - modal = $('#modal_merge_info').modal modal: true, show:false  
26 -  
27 - $('.how_to_merge_link').bind "click", ->  
28 - modal.show()  
29 - $('.modal-header .close').bind "click", ->  
30 - modal.hide() 25 + modal = $('#modal_merge_info').modal(show: false)
31 26
32 # Local jQuery finder 27 # Local jQuery finder
33 $: (selector) -> 28 $: (selector) ->
app/assets/javascripts/notes.js
@@ -227,10 +227,11 @@ var NoteList = { @@ -227,10 +227,11 @@ var NoteList = {
227 // Show the attachment delete link 227 // Show the attachment delete link
228 note.find(".js-note-attachment-delete").show(); 228 note.find(".js-note-attachment-delete").show();
229 229
  230 + GitLab.GfmAutoComplete.setup();
  231 +
230 var form = note.find(".note-edit-form"); 232 var form = note.find(".note-edit-form");
231 form.show(); 233 form.show();
232 234
233 -  
234 var textarea = form.find("textarea"); 235 var textarea = form.find("textarea");
235 var p = $("<p></p>").text(textarea.val()); 236 var p = $("<p></p>").text(textarea.val());
236 var hidden_div = $('<div class="note-original-content"></div>').append(p); 237 var hidden_div = $('<div class="note-original-content"></div>').append(p);
app/assets/javascripts/wikis.js.coffee
1 class Wikis 1 class Wikis
2 constructor: -> 2 constructor: ->
3 - modal = $('#modal-new-wiki').modal({modal: true, show:false})  
4 -  
5 - $('.add-new-wiki').bind "click", ->  
6 - modal.show()  
7 -  
8 $('.build-new-wiki').bind "click", -> 3 $('.build-new-wiki').bind "click", ->
9 field = $('#new_wiki_path') 4 field = $('#new_wiki_path')
10 slug = field.val() 5 slug = field.val()
@@ -13,7 +8,5 @@ class Wikis @@ -13,7 +8,5 @@ class Wikis
13 if(slug.length > 0) 8 if(slug.length > 0)
14 location.href = path + "/" + slug 9 location.href = path + "/" + slug
15 10
16 - $('.modal-header .close').bind "click", ->  
17 - modal.hide()  
18 11
19 @Wikis = Wikis 12 @Wikis = Wikis
app/assets/stylesheets/common.scss
@@ -81,33 +81,6 @@ span.update-author { @@ -81,33 +81,6 @@ span.update-author {
81 font-weight: normal; 81 font-weight: normal;
82 } 82 }
83 83
84 -form {  
85 - @extend .form-horizontal;  
86 -  
87 - .actions {  
88 - @extend .form-actions;  
89 - }  
90 -  
91 - .clearfix {  
92 - @extend .control-group;  
93 - }  
94 -  
95 - .input {  
96 - @extend .controls;  
97 - }  
98 -  
99 - label {  
100 - @extend .control-label;  
101 - }  
102 - .xlarge {  
103 - @extend .input-xlarge;  
104 - }  
105 - .xxlarge {  
106 - @extend .input-xxlarge;  
107 - }  
108 -}  
109 -  
110 -  
111 .field_with_errors { 84 .field_with_errors {
112 display: inline; 85 display: inline;
113 } 86 }
@@ -121,15 +94,6 @@ ul.breadcrumb { @@ -121,15 +94,6 @@ ul.breadcrumb {
121 } 94 }
122 95
123 a { 96 a {
124 - color: #474D57;  
125 - font-weight: bold;  
126 - font-size: 14px;  
127 - }  
128 -}  
129 -  
130 -input[type=text] {  
131 - &.large_text {  
132 - padding: 6px;  
133 font-size: 16px; 97 font-size: 16px;
134 } 98 }
135 } 99 }
app/assets/stylesheets/gitlab_bootstrap.scss
@@ -2,11 +2,49 @@ @@ -2,11 +2,49 @@
2 $baseFontSize: 13px !default; 2 $baseFontSize: 13px !default;
3 $baseLineHeight: 18px !default; 3 $baseLineHeight: 18px !default;
4 4
5 -// BOOTSTRAP  
6 -@import "bootstrap"; 5 +/**
  6 + * BOOTSTRAP
  7 + */
  8 +@import "bootstrap/variables";
  9 +@import "bootstrap/mixins";
  10 +@import "bootstrap/reset";
  11 +@import "bootstrap/scaffolding";
  12 +@import "bootstrap/grid";
  13 +@import "bootstrap/layouts";
  14 +@import "bootstrap/type";
  15 +@import "bootstrap/code";
  16 +@import "bootstrap/forms";
  17 +@import "bootstrap/tables";
  18 +@import "bootstrap/sprites";
  19 +@import "bootstrap/dropdowns";
  20 +@import "bootstrap/wells";
  21 +@import "bootstrap/component-animations";
  22 +@import "bootstrap/close";
  23 +@import "bootstrap/button-groups";
  24 +@import "bootstrap/alerts";
  25 +@import "bootstrap/navs";
  26 +@import "bootstrap/navbar";
  27 +@import "bootstrap/breadcrumbs";
  28 +@import "bootstrap/pagination";
  29 +@import "bootstrap/pager";
  30 +@import "bootstrap/modals";
  31 +@import "bootstrap/tooltip";
  32 +@import "bootstrap/popovers";
  33 +@import "bootstrap/thumbnails";
  34 +@import "bootstrap/media";
  35 +@import "bootstrap/labels-badges";
  36 +@import "bootstrap/progress-bars";
  37 +@import "bootstrap/accordion";
  38 +@import "bootstrap/carousel";
  39 +@import "bootstrap/hero-unit";
  40 +@import "bootstrap/utilities";
7 @import "bootstrap/responsive-utilities"; 41 @import "bootstrap/responsive-utilities";
8 @import "bootstrap/responsive-1200px-min"; 42 @import "bootstrap/responsive-1200px-min";
9 43
  44 +/**
  45 + * Font icons
  46 + *
  47 + */
10 @import "font-awesome"; 48 @import "font-awesome";
11 49
12 /** 50 /**
@@ -26,3 +64,4 @@ $baseLineHeight: 18px !default; @@ -26,3 +64,4 @@ $baseLineHeight: 18px !default;
26 @import "gitlab_bootstrap/files.scss"; 64 @import "gitlab_bootstrap/files.scss";
27 @import "gitlab_bootstrap/tables.scss"; 65 @import "gitlab_bootstrap/tables.scss";
28 @import "gitlab_bootstrap/lists.scss"; 66 @import "gitlab_bootstrap/lists.scss";
  67 +@import "gitlab_bootstrap/forms.scss";
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
@@ -10,15 +10,34 @@ @@ -10,15 +10,34 @@
10 * 10 *
11 */ 11 */
12 .ui-box { 12 .ui-box {
13 - background: #F9F9F9; 13 + background: #FFF;
14 margin-bottom: 20px; 14 margin-bottom: 20px;
15 border: 1px solid #CCC; 15 border: 1px solid #CCC;
16 word-wrap: break-word; 16 word-wrap: break-word;
17 - @include solid-shade; 17 +
  18 + &.small-box {
  19 + margin-bottom: 10px;
  20 +
  21 + .title {
  22 + font-size: 13px;
  23 + line-height: 30px;
  24 +
  25 + a {
  26 + color: #666;
  27 + &:hover {
  28 + text-decoration: underline;
  29 + }
  30 + }
  31 + }
  32 + }
18 33
19 &.ui-box-show { 34 &.ui-box-show {
20 margin:20px 0; 35 margin:20px 0;
21 background: #FFF; 36 background: #FFF;
  37 +
  38 + .control-group {
  39 + margin-bottom: 0;
  40 + }
22 } 41 }
23 42
24 &.ui-box-danger { 43 &.ui-box-danger {
@@ -71,10 +90,6 @@ @@ -71,10 +90,6 @@
71 border-top: 1px solid #eee; 90 border-top: 1px solid #eee;
72 } 91 }
73 92
74 - &.white {  
75 - background: #fff;  
76 - }  
77 -  
78 ul { 93 ul {
79 margin: 0; 94 margin: 0;
80 } 95 }
@@ -102,6 +117,8 @@ @@ -102,6 +117,8 @@
102 117
103 .btn { 118 .btn {
104 vertical-align: middle; 119 vertical-align: middle;
  120 + padding: 4px 12px;
  121 + @include box-shadow(0 0px 1px 1px #f2f2f2);
105 } 122 }
106 123
107 .nav-pills { 124 .nav-pills {
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 .btn { 1 .btn {
  2 + display: inline-block;
  3 + padding: 6px 12px;
  4 + margin-bottom: 0;
  5 + font-size: 13px;
  6 + line-height: $baseLineHeight;
  7 + text-align: center;
  8 + vertical-align: middle;
  9 + cursor: pointer;
  10 + border: 1px solid #BBB;
  11 + color: $style_color;
  12 + @include border-radius($baseBorderRadius);
  13 + @include box-shadow(inset 0 1px 0 rgba(255,255,255,.2));
2 @include linear-gradient(#f1f1f1, #e1e1e1); 14 @include linear-gradient(#f1f1f1, #e1e1e1);
3 text-shadow: 0 1px 1px #FFF; 15 text-shadow: 0 1px 1px #FFF;
4 - border-color: #BBB; 16 + text-decoration: none;
5 17
  18 + &.hover,
6 &:hover { 19 &:hover {
  20 + color: $style_color;
7 background: #f1f1f1; 21 background: #f1f1f1;
8 - @include linear-gradient(#fAfAfA, #f1f1f1);  
9 border-color: #AAA; 22 border-color: #AAA;
10 - color: #333; 23 + text-decoration: none;
  24 + @include linear-gradient(#fAfAfA, #f1f1f1);
11 } 25 }
12 26
13 - &.btn-primary {  
14 - background: #2a79A3;  
15 - @include linear-gradient(#47A7b7, #2585b5);  
16 - border-color: #2A79A3;  
17 - color: #fff;  
18 - text-shadow: 0 1px 1px #268;  
19 - &:hover {  
20 - background: $primary_color;  
21 - color: #fff;  
22 - } 27 + &.focus,
  28 + &:focus {
  29 + text-decoration: none;
  30 + @include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
  31 + }
23 32
24 - &.disabled {  
25 - color: #fff;  
26 - background: $primary_color;  
27 - } 33 + &.active,
  34 + &:active {
  35 + background-image: none;
  36 + outline: 0;
  37 + text-decoration: none;
  38 + @include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
28 } 39 }
29 40
30 - &.btn-info {  
31 - background: #5aB9C3;  
32 - border-color: $primary_color;  
33 - color: #fff;  
34 - text-shadow: 0 1px 1px #268;  
35 - &:hover {  
36 - background: $primary_color;  
37 - color: #fff;  
38 - } 41 + &.disabled,
  42 + &[disabled] {
  43 + cursor: default;
  44 + background-image: none;
  45 + @include opacity(65);
  46 + @include box-shadow(none);
  47 + }
39 48
40 - &.disabled {  
41 - color: #fff;  
42 - background: $primary_color; 49 + &.btn-primary {
  50 + color: #FFF;
  51 + border-color: #189;
  52 + text-shadow: 0 1px 1px #189;
  53 + @include linear-gradient(#4AC, #289);
  54 +
  55 + &.hover,
  56 + &:hover,
  57 + &.disabled,
  58 + &[disabled] {
  59 + color: #FFF;
  60 + background: #389;
43 } 61 }
44 } 62 }
45 63
46 &.btn-success { 64 &.btn-success {
47 - &:hover {  
48 - background: #51a351; 65 + color: #FFF;
  66 + border-color: #1A1;
  67 + text-shadow: 0 1px 1px #FFF;
  68 + text-shadow: 0 1px 1px #181;
  69 + @include linear-gradient(#62C452, #51a351);
  70 +
  71 +
  72 + &.hover,
  73 + &:hover,
  74 + &.disabled,
  75 + &[disabled] {
  76 + color: #FFF;
  77 + background: #2A2;
49 } 78 }
  79 + }
  80 +
  81 + &.btn-danger {
  82 + color: #FFF;
  83 + text-shadow: 0 1px 1px #811;
  84 + border-color: #BD362F;
  85 + @include linear-gradient(#EE5F5B, #BD362F);
50 86
51 - &.disabled {  
52 - color: #fff;  
53 - background: #2b2; 87 +
  88 + &.hover,
  89 + &:hover,
  90 + &.disabled,
  91 + &[disabled] {
  92 + color: #FFF;
  93 + background: #A22;
54 } 94 }
55 } 95 }
56 96
  97 + &.btn-new {
  98 + @extend .btn-success;
  99 + }
  100 +
57 &.btn-create { 101 &.btn-create {
58 @extend .wide; 102 @extend .wide;
59 @extend .btn-success; 103 @extend .btn-success;
@@ -67,12 +111,6 @@ @@ -67,12 +111,6 @@
67 &.btn-close, 111 &.btn-close,
68 &.btn-remove { 112 &.btn-remove {
69 @extend .btn-danger; 113 @extend .btn-danger;
70 - border-color: #BD362F;  
71 -  
72 - &:hover {  
73 - color: #fff;  
74 - background: #EE4E49;  
75 - }  
76 } 114 }
77 115
78 &.btn-cancel { 116 &.btn-cancel {
@@ -84,13 +122,9 @@ @@ -84,13 +122,9 @@
84 padding-right: 20px; 122 padding-right: 20px;
85 } 123 }
86 124
87 - &.small {  
88 - @extend .btn-small;  
89 - }  
90 -  
91 - &.active {  
92 - border-color: #aaa;  
93 - background-color: #ccc; 125 + &.btn-small {
  126 + padding: 2px 10px;
  127 + font-size: 12px;
94 } 128 }
95 129
96 &.btn-tiny { 130 &.btn-tiny {
@@ -104,9 +138,4 @@ @@ -104,9 +138,4 @@
104 margin-right: 7px; 138 margin-right: 7px;
105 float: left; 139 float: left;
106 } 140 }
107 -  
108 - &.padded {  
109 - margin-right: 3px;  
110 - padding: 4px 10px 4px;  
111 - }  
112 } 141 }
app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -48,7 +48,13 @@ @@ -48,7 +48,13 @@
48 line-height: 36px; 48 line-height: 36px;
49 } 49 }
50 50
51 -p.slead { color: #456; font-size: 16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; } 51 +.slead {
  52 + color: #666;
  53 + font-size: 14px;
  54 + margin-bottom: 12px;
  55 + font-weight: normal;
  56 + line-height: 24px;
  57 +}
52 58
53 /** FORMS **/ 59 /** FORMS **/
54 input[type='search'].search-text-input { 60 input[type='search'].search-text-input {
@@ -66,7 +72,7 @@ input[type=&#39;text&#39;].danger { @@ -66,7 +72,7 @@ input[type=&#39;text&#39;].danger {
66 text-shadow: 0 1px 1px #fff 72 text-shadow: 0 1px 1px #fff
67 } 73 }
68 74
69 -fieldset legend { font-size: 17px; } 75 +fieldset legend { font-size: 15px; }
70 76
71 .tab-content { 77 .tab-content {
72 overflow: visible; 78 overflow: visible;
@@ -90,3 +96,11 @@ pre.well-pre { @@ -90,3 +96,11 @@ pre.well-pre {
90 border-radius: 0; 96 border-radius: 0;
91 color: #555; 97 color: #555;
92 } 98 }
  99 +
  100 +.input-append .btn.active, .input-prepend .btn.active {
  101 + background: #CCC;
  102 + border-color: #BBB;
  103 + text-shadow: 0 1px 1px #fff;
  104 + font-weight: bold;
  105 + @include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
  106 +}
app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -3,18 +3,18 @@ @@ -3,18 +3,18 @@
3 * 3 *
4 */ 4 */
5 .file-holder { 5 .file-holder {
6 - border: 1px solid #BBB; 6 + border: 1px solid #CCC;
7 margin-bottom: 1em; 7 margin-bottom: 1em;
8 - @include solid-shade;  
9 8
10 .file-title { 9 .file-title {
11 border-bottom: 1px solid #bbb; 10 border-bottom: 1px solid #bbb;
12 @include bg-dark-gray-gradient; 11 @include bg-dark-gray-gradient;
  12 + text-shadow: 0 1px 1px #fff;
13 margin: 0; 13 margin: 0;
14 font-weight: normal; 14 font-weight: normal;
15 font-weight: bold; 15 font-weight: bold;
16 text-align: left; 16 text-align: left;
17 - color: #666; 17 + color: $style_color;
18 padding: 9px 10px; 18 padding: 9px 10px;
19 height: 18px; 19 height: 18px;
20 20
app/assets/stylesheets/gitlab_bootstrap/forms.scss 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +form {
  2 + @extend .form-horizontal;
  3 +
  4 + label {
  5 + @extend .control-label;
  6 + }
  7 +}
  8 +
  9 +input {
  10 + &.input-xpadding {
  11 + padding: 6px 10px;
  12 + }
  13 +}
  14 +
  15 +.control-group {
  16 + .control-label {
  17 + padding-top: 6px;
  18 + }
  19 + .controls {
  20 + input, textarea {
  21 + padding: 6px 10px;
  22 + }
  23 +
  24 + input[type="radio"], input[type="checkbox"] {
  25 + margin-top: 6px;
  26 + }
  27 + }
  28 +}
  29 +
app/assets/stylesheets/gitlab_bootstrap/lists.scss
@@ -6,7 +6,6 @@ @@ -6,7 +6,6 @@
6 margin: 0; 6 margin: 0;
7 list-style: none; 7 list-style: none;
8 li { 8 li {
9 - background-color: #FFF;  
10 padding: 10px; 9 padding: 10px;
11 min-height: 20px; 10 min-height: 20px;
12 border-bottom: 1px solid #eee; 11 border-bottom: 1px solid #eee;
@@ -84,4 +83,13 @@ ul.bordered-list { @@ -84,4 +83,13 @@ ul.bordered-list {
84 a { color: #777; } 83 a { color: #777; }
85 } 84 }
86 } 85 }
  86 +
  87 + &.top-list {
  88 + li:first-child {
  89 + padding-top: 0;
  90 + h4, h5 {
  91 + margin-top: 0;
  92 + }
  93 + }
  94 + }
87 } 95 }
app/assets/stylesheets/gitlab_bootstrap/mixins.scss
@@ -90,7 +90,6 @@ @@ -90,7 +90,6 @@
90 @mixin page-title { 90 @mixin page-title {
91 color: $style_color; 91 color: $style_color;
92 font-size: 20px; 92 font-size: 20px;
93 - font-weight: normal;  
94 line-height: 1.5; 93 line-height: 1.5;
95 margin-top: 0px; 94 margin-top: 0px;
96 margin-bottom: 15px; 95 margin-bottom: 15px;
app/assets/stylesheets/gitlab_bootstrap/nav.scss
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 > li > a { 10 > li > a {
11 @include border-radius(0); 11 @include border-radius(0);
12 } 12 }
  13 +
13 &.nav-stacked { 14 &.nav-stacked {
14 > li > a { 15 > li > a {
15 border-left: 4px solid #EEE; 16 border-left: 4px solid #EEE;
@@ -30,6 +31,12 @@ @@ -30,6 +31,12 @@
30 } 31 }
31 } 32 }
32 } 33 }
  34 +
  35 + &.nav-pills-small {
  36 + > li > a {
  37 + padding: 8px 12px;
  38 + }
  39 + }
33 } 40 }
34 41
35 .nav-pills > .active > a > i[class^="icon-"] { background: inherit; } 42 .nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
app/assets/stylesheets/gitlab_bootstrap/tables.scss
1 table { 1 table {
2 @extend .table; 2 @extend .table;
3 @extend .table-striped; 3 @extend .table-striped;
4 - @include solid-shade;  
5 - border: 1px solid #bbb; 4 + border: 1px solid #CCC;
6 width: 100%; 5 width: 100%;
7 6
8 &.low { 7 &.low {
@@ -20,7 +19,7 @@ table { @@ -20,7 +19,7 @@ table {
20 th { 19 th {
21 font-weight: bold; 20 font-weight: bold;
22 vertical-align: middle; 21 vertical-align: middle;
23 - border-bottom: 1px solid #bbb; 22 + border-bottom: 1px solid #CCC;
24 text-shadow: 0 1px 1px #fff; 23 text-shadow: 0 1px 1px #fff;
25 @include bg-dark-gray-gradient; 24 @include bg-dark-gray-gradient;
26 25
@@ -46,11 +45,11 @@ table { @@ -46,11 +45,11 @@ table {
46 } 45 }
47 46
48 &:first-child { 47 &:first-child {
49 - border-left: 1px solid #bbb; 48 + border-left: 1px solid #CCC;
50 } 49 }
51 50
52 &:last-child { 51 &:last-child {
53 - border-right: 1px solid #bbb; 52 + border-right: 1px solid #CCC;
54 } 53 }
55 } 54 }
56 55
app/assets/stylesheets/gitlab_bootstrap/typography.scss
@@ -2,6 +2,10 @@ @@ -2,6 +2,10 @@
2 * Headers 2 * Headers
3 * 3 *
4 */ 4 */
  5 +h1, h2, h3, h4, h5, h6 {
  6 + font-weight: 500;
  7 + line-height: 1.1;
  8 +}
5 9
6 h1.page-title { 10 h1.page-title {
7 @include page-title; 11 @include page-title;
@@ -48,13 +52,6 @@ a { @@ -48,13 +52,6 @@ a {
48 text-decoration: underline; 52 text-decoration: underline;
49 } 53 }
50 54
51 - &.btn {  
52 - color: $style_color;  
53 - &:hover {  
54 - color: $style_color;  
55 - }  
56 - }  
57 -  
58 &.dark { 55 &.dark {
59 color: $style_color; 56 color: $style_color;
60 } 57 }
app/assets/stylesheets/sections/commits.scss
@@ -421,8 +421,8 @@ @@ -421,8 +421,8 @@
421 421
422 .commits-compare-switch{ 422 .commits-compare-switch{
423 background: url("switch_icon.png") no-repeat center center; 423 background: url("switch_icon.png") no-repeat center center;
424 - width: 16px;  
425 - height: 18px; 424 + width: 22px;
  425 + height: 22px;
426 text-indent: -9999px; 426 text-indent: -9999px;
427 float: left; 427 float: left;
428 margin-right: 9px; 428 margin-right: 9px;
@@ -471,3 +471,7 @@ li.commit { @@ -471,3 +471,7 @@ li.commit {
471 } 471 }
472 } 472 }
473 } 473 }
  474 +
  475 +.commit-breadcrumb {
  476 + padding: 0;
  477 +}
app/assets/stylesheets/sections/issues.scss
@@ -44,7 +44,7 @@ input.check_all_issues { @@ -44,7 +44,7 @@ input.check_all_issues {
44 margin: 0; 44 margin: 0;
45 margin-right: 10px; 45 margin-right: 10px;
46 position: relative; 46 position: relative;
47 - top: 8px; 47 + top: 10px;
48 height: 22px; 48 height: 22px;
49 } 49 }
50 50
@@ -52,6 +52,10 @@ input.check_all_issues { @@ -52,6 +52,10 @@ input.check_all_issues {
52 .title { 52 .title {
53 height: 40px; 53 height: 40px;
54 } 54 }
  55 +
  56 + form {
  57 + margin: 0;
  58 + }
55 } 59 }
56 60
57 .btn.close_issue { 61 .btn.close_issue {
@@ -88,14 +92,11 @@ input.check_all_issues { @@ -88,14 +92,11 @@ input.check_all_issues {
88 } 92 }
89 93
90 .update_selected_issues { 94 .update_selected_issues {
91 - position: relative;  
92 - top:5px;  
93 margin-left: 4px; 95 margin-left: 4px;
94 - float: left;  
95 } 96 }
96 97
97 .update_issues_text { 98 .update_issues_text {
98 - padding: 3px; 99 + padding: 5px;
99 line-height: 28px; 100 line-height: 28px;
100 float: left; 101 float: left;
101 color: #479; 102 color: #479;
app/assets/stylesheets/sections/nav.scss
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 7
8 ul { 8 ul {
9 margin: auto; 9 margin: auto;
10 - height: 42px; 10 + height: 40px;
11 overflow: hidden; 11 overflow: hidden;
12 .count { 12 .count {
13 font-weight: normal; 13 font-weight: normal;
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 text-align: center; 74 text-align: center;
75 font-weight: normal; 75 font-weight: normal;
76 height: 38px; 76 height: 38px;
77 - line-height: 36px; 77 + line-height: 34px;
78 color: #777; 78 color: #777;
79 text-shadow: 0 1px 1px white; 79 text-shadow: 0 1px 1px white;
80 padding: 0 10px; 80 padding: 0 10px;
app/assets/stylesheets/sections/projects.scss
1 .new_project, 1 .new_project,
2 .edit_project { 2 .edit_project {
3 - .project_name_holder {  
4 - input,  
5 - label {  
6 - font-size: 16px;  
7 - line-height: 20px;  
8 - padding: 8px;  
9 - }  
10 - .btn {  
11 - padding: 6px 10px;  
12 - margin-left: 10px;  
13 - margin-bottom: 8px;  
14 - }  
15 - }  
16 - .adv_settings {  
17 - h6 { margin-left: 40px; }  
18 - }  
19 -  
20 fieldset.features { 3 fieldset.features {
21 .control-label { 4 .control-label {
22 font-weight: bold; 5 font-weight: bold;
@@ -30,6 +13,10 @@ @@ -30,6 +13,10 @@
30 padding: 4px 7px; 13 padding: 4px 7px;
31 border: 1px solid #CCC; 14 border: 1px solid #CCC;
32 margin-bottom: 20px; 15 margin-bottom: 20px;
  16 +
  17 + .btn {
  18 + padding: 4px 12px;
  19 + }
33 } 20 }
34 21
35 .project_clone_holder { 22 .project_clone_holder {
@@ -114,7 +101,7 @@ ul.nav.nav-projects-tabs { @@ -114,7 +101,7 @@ ul.nav.nav-projects-tabs {
114 .public-clone { 101 .public-clone {
115 background: #333; 102 background: #333;
116 color: #f5f5f5; 103 color: #f5f5f5;
117 - padding: 5px 10px; 104 + padding: 6px 10px;
118 margin: 1px; 105 margin: 1px;
119 font-weight: normal; 106 font-weight: normal;
120 } 107 }
app/assets/stylesheets/sections/tree.scss
@@ -104,6 +104,8 @@ @@ -104,6 +104,8 @@
104 } 104 }
105 105
106 .tree-btn-group { 106 .tree-btn-group {
  107 + top: 2px;
  108 +
107 .btn { 109 .btn {
108 margin-right: 0px; 110 margin-right: 0px;
109 padding: 2px 10px; 111 padding: 2px 10px;
app/assets/stylesheets/themes/ui_mars.scss
@@ -31,8 +31,4 @@ @@ -31,8 +31,4 @@
31 border-left: 1px solid #666; 31 border-left: 1px solid #666;
32 } 32 }
33 } 33 }
34 -  
35 - .main-nav {  
36 - box-shadow: 0 -1px 0 white inset;  
37 - }  
38 } 34 }
app/contexts/filter_context.rb
@@ -11,8 +11,8 @@ class FilterContext @@ -11,8 +11,8 @@ class FilterContext
11 end 11 end
12 12
13 def apply_filter items 13 def apply_filter items
14 - if params[:project_id]  
15 - items = items.by_project(params[:project_id]) 14 + if params[:project_id].present?
  15 + items = items.where(project_id: params[:project_id])
16 end 16 end
17 17
18 if params[:search].present? 18 if params[:search].present?
app/contexts/merge_requests_load_context.rb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 # based on filtering passed via params for @project 2 # based on filtering passed via params for @project
3 class MergeRequestsLoadContext < BaseContext 3 class MergeRequestsLoadContext < BaseContext
4 def execute 4 def execute
5 - type = params[:f] 5 + type = params[:status]
6 6
7 merge_requests = project.merge_requests 7 merge_requests = project.merge_requests
8 8
app/contexts/search_context.rb
@@ -11,7 +11,7 @@ class SearchContext @@ -11,7 +11,7 @@ class SearchContext
11 return result unless query.present? 11 return result unless query.present?
12 12
13 projects = Project.where(id: project_ids) 13 projects = Project.where(id: project_ids)
14 - result[:projects] = projects.search(query).limit(10) 14 + result[:projects] = projects.search(query).limit(20)
15 15
16 # Search inside singe project 16 # Search inside singe project
17 project = projects.first if projects.length == 1 17 project = projects.first if projects.length == 1
@@ -19,8 +19,8 @@ class SearchContext @@ -19,8 +19,8 @@ class SearchContext
19 if params[:search_code].present? 19 if params[:search_code].present?
20 result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo? 20 result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo?
21 else 21 else
22 - result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).limit(10)  
23 - result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10) 22 + result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).limit(20)
  23 + result[:issues] = Issue.where(project_id: project_ids).search(query).limit(20)
24 result[:wiki_pages] = [] 24 result[:wiki_pages] = []
25 end 25 end
26 result 26 result
app/controllers/profiles/groups_controller.rb
@@ -2,7 +2,7 @@ class Profiles::GroupsController &lt; ApplicationController @@ -2,7 +2,7 @@ class Profiles::GroupsController &lt; ApplicationController
2 layout "profile" 2 layout "profile"
3 3
4 def index 4 def index
5 - @groups = current_user.authorized_groups.page(params[:page]).per(20) 5 + @user_groups = current_user.users_groups.page(params[:page]).per(20)
6 end 6 end
7 7
8 def leave 8 def leave
app/controllers/projects/branches_controller.rb
@@ -11,6 +11,10 @@ class Projects::BranchesController &lt; Projects::ApplicationController @@ -11,6 +11,10 @@ class Projects::BranchesController &lt; Projects::ApplicationController
11 @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30) 11 @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30)
12 end 12 end
13 13
  14 + def recent
  15 + @branches = @repository.recent_branches
  16 + end
  17 +
14 def create 18 def create
15 @repository.add_branch(params[:branch_name], params[:ref]) 19 @repository.add_branch(params[:branch_name], params[:ref])
16 20
app/controllers/projects/edit_tree_controller.rb
@@ -10,7 +10,7 @@ class Projects::EditTreeController &lt; Projects::ApplicationController @@ -10,7 +10,7 @@ class Projects::EditTreeController &lt; Projects::ApplicationController
10 before_filter :edit_requirements, only: [:show, :update] 10 before_filter :edit_requirements, only: [:show, :update]
11 11
12 def show 12 def show
13 - @last_commit = @project.repository.last_commit_for(@ref, @path).sha 13 + @last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, @ref, @path).sha
14 end 14 end
15 15
16 def update 16 def update
app/controllers/projects/repositories_controller.rb
@@ -4,10 +4,6 @@ class Projects::RepositoriesController &lt; Projects::ApplicationController @@ -4,10 +4,6 @@ class Projects::RepositoriesController &lt; Projects::ApplicationController
4 before_filter :authorize_code_access! 4 before_filter :authorize_code_access!
5 before_filter :require_non_empty_project 5 before_filter :require_non_empty_project
6 6
7 - def show  
8 - @activities = @repository.commits_with_refs(20)  
9 - end  
10 -  
11 def stats 7 def stats
12 @stats = Gitlab::Git::Stats.new(@repository.raw, @repository.root_ref) 8 @stats = Gitlab::Git::Stats.new(@repository.raw, @repository.root_ref)
13 @graph = @stats.graph 9 @graph = @stats.graph
app/controllers/users_groups_controller.rb
@@ -13,7 +13,8 @@ class UsersGroupsController &lt; ApplicationController @@ -13,7 +13,8 @@ class UsersGroupsController &lt; ApplicationController
13 end 13 end
14 14
15 def update 15 def update
16 - # TODO: implement 16 + @member = @group.users_groups.find(params[:id])
  17 + @member.update_attributes(params[:users_group])
17 end 18 end
18 19
19 def destroy 20 def destroy
app/helpers/commits_helper.rb
@@ -15,61 +15,9 @@ module CommitsHelper @@ -15,61 +15,9 @@ module CommitsHelper
15 commit_person_link(commit, options.merge(source: :committer)) 15 commit_person_link(commit, options.merge(source: :committer))
16 end 16 end
17 17
18 - def identification_type(line)  
19 - if line[0] == "+"  
20 - "new"  
21 - elsif line[0] == "-"  
22 - "old"  
23 - else  
24 - nil  
25 - end  
26 - end  
27 -  
28 - def build_line_anchor(diff, line_new, line_old)  
29 - "#{hexdigest(diff.new_path)}_#{line_old}_#{line_new}"  
30 - end  
31 -  
32 def each_diff_line(diff, index) 18 def each_diff_line(diff, index)
33 - diff_arr = diff.diff.lines.to_a  
34 -  
35 - line_old = 1  
36 - line_new = 1  
37 - type = nil  
38 -  
39 - lines_arr = ::Gitlab::InlineDiff.processing diff_arr  
40 - lines_arr.each do |line|  
41 - next if line.match(/^\-\-\- \/dev\/null/)  
42 - next if line.match(/^\+\+\+ \/dev\/null/)  
43 - next if line.match(/^\-\-\- a/)  
44 - next if line.match(/^\+\+\+ b/)  
45 -  
46 - full_line = html_escape(line.gsub(/\n/, ''))  
47 - full_line = ::Gitlab::InlineDiff.replace_markers full_line  
48 -  
49 - if line.match(/^@@ -/)  
50 - type = "match"  
51 -  
52 - line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0  
53 - line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0  
54 -  
55 - next if line_old == 1 && line_new == 1 #top of file  
56 - yield(full_line, type, nil, nil, nil)  
57 - next  
58 - else  
59 - type = identification_type(line)  
60 - line_code = build_line_anchor(diff, line_new, line_old)  
61 - yield(full_line, type, line_code, line_new, line_old)  
62 - end  
63 -  
64 -  
65 - if line[0] == "+"  
66 - line_new += 1  
67 - elsif line[0] == "-"  
68 - line_old += 1  
69 - else  
70 - line_new += 1  
71 - line_old += 1  
72 - end 19 + Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old|
  20 + yield(full_line, type, line_code, line_new, line_old)
73 end 21 end
74 end 22 end
75 23
app/helpers/dashboard_helper.rb
1 module DashboardHelper 1 module DashboardHelper
2 - def dashboard_filter_path(entity, options={}) 2 + def filter_path(entity, options={})
3 exist_opts = { 3 exist_opts = {
4 status: params[:status], 4 status: params[:status],
5 project_id: params[:project_id], 5 project_id: params[:project_id],
@@ -7,12 +7,9 @@ module DashboardHelper @@ -7,12 +7,9 @@ module DashboardHelper
7 7
8 options = exist_opts.merge(options) 8 options = exist_opts.merge(options)
9 9
10 - case entity  
11 - when 'issue' then  
12 - issues_dashboard_path(options)  
13 - when 'merge_request'  
14 - merge_requests_dashboard_path(options)  
15 - end 10 + path = request.path
  11 + path << "?#{options.to_param}"
  12 + path
16 end 13 end
17 14
18 def entities_per_project project, entity 15 def entities_per_project project, entity
app/helpers/groups_helper.rb
1 module GroupsHelper 1 module GroupsHelper
2 - def group_filter_path(entity, options={})  
3 - exist_opts = {  
4 - status: params[:status],  
5 - project_id: params[:project_id],  
6 - }  
7 -  
8 - options = exist_opts.merge(options)  
9 -  
10 - case entity  
11 - when 'issue' then  
12 - issues_group_path(@group, options)  
13 - when 'merge_request'  
14 - merge_requests_group_path(@group, options)  
15 - end  
16 - end  
17 -  
18 def remove_user_from_group_message(group, user) 2 def remove_user_from_group_message(group, user)
19 "You are going to remove #{user.name} from #{group.name} Group. Are you sure?" 3 "You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
20 end 4 end
app/helpers/notifications_helper.rb
1 module NotificationsHelper 1 module NotificationsHelper
  2 + def notification_icon(notification)
  3 + if notification.disabled?
  4 + content_tag :i, nil, class: 'icon-circle cred'
  5 + elsif notification.participating?
  6 + content_tag :i, nil, class: 'icon-circle cblue'
  7 + elsif notification.watch?
  8 + content_tag :i, nil, class: 'icon-circle cgreen'
  9 + else
  10 + content_tag :i, nil, class: 'icon-circle-blank cblue'
  11 + end
  12 + end
2 end 13 end
app/helpers/tree_helper.rb
@@ -39,12 +39,12 @@ module TreeHelper @@ -39,12 +39,12 @@ module TreeHelper
39 # 39 #
40 # Returns boolean 40 # Returns boolean
41 def markup?(filename) 41 def markup?(filename)
42 - filename.end_with?(*%w(.textile .rdoc .org .creole  
43 - .mediawiki .rst .asciidoc .pod)) 42 + filename.downcase.end_with?(*%w(.textile .rdoc .org .creole
  43 + .mediawiki .rst .asciidoc .pod))
44 end 44 end
45 45
46 def gitlab_markdown?(filename) 46 def gitlab_markdown?(filename)
47 - filename.end_with?(*%w(.mdown .md .markdown)) 47 + filename.downcase.end_with?(*%w(.mdown .md .markdown))
48 end 48 end
49 49
50 def plain_text_readme? filename 50 def plain_text_readme? filename
@@ -57,6 +57,8 @@ module TreeHelper @@ -57,6 +57,8 @@ module TreeHelper
57 end 57 end
58 58
59 def allowed_tree_edit? 59 def allowed_tree_edit?
  60 + return false unless @repository.branch_names.include?(@ref)
  61 +
60 if @project.protected_branch? @ref 62 if @project.protected_branch? @ref
61 can?(current_user, :push_code_to_protected_branches, @project) 63 can?(current_user, :push_code_to_protected_branches, @project)
62 else 64 else
app/models/deprecated/user_team.rb
  1 +# Will be removed in 6.1 with tables
  2 +#
1 # == Schema Information 3 # == Schema Information
2 # 4 #
3 # Table name: user_teams 5 # Table name: user_teams
app/models/deprecated/user_team_project_relationship.rb
  1 +# Will be removed in 6.1 with tables
  2 +#
1 # == Schema Information 3 # == Schema Information
2 # 4 #
3 # Table name: user_team_project_relationships 5 # Table name: user_team_project_relationships
app/models/deprecated/user_team_user_relationship.rb
  1 +# Will be removed in 6.1 with tables
  2 +#
1 # == Schema Information 3 # == Schema Information
2 # 4 #
3 # Table name: user_team_user_relationships 5 # Table name: user_team_user_relationships
app/models/merge_request.rb
@@ -149,11 +149,12 @@ class MergeRequest &lt; ActiveRecord::Base @@ -149,11 +149,12 @@ class MergeRequest &lt; ActiveRecord::Base
149 end 149 end
150 150
151 def unmerged_diffs 151 def unmerged_diffs
152 - if for_fork?  
153 - diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite  
154 - else  
155 - diffs = target_project.repository.diffs_between(source_branch, target_branch)  
156 - end 152 + diffs = if for_fork?
  153 + Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
  154 + else
  155 + Gitlab::Git::Diff.between(project.repository, source_branch, target_branch)
  156 + end
  157 +
157 diffs ||= [] 158 diffs ||= []
158 diffs 159 diffs
159 end 160 end
app/models/note.rb
@@ -50,6 +50,9 @@ class Note &lt; ActiveRecord::Base @@ -50,6 +50,9 @@ class Note &lt; ActiveRecord::Base
50 scope :inc_author_project, ->{ includes(:project, :author) } 50 scope :inc_author_project, ->{ includes(:project, :author) }
51 scope :inc_author, ->{ includes(:author) } 51 scope :inc_author, ->{ includes(:author) }
52 52
  53 + serialize :st_diff
  54 + before_create :set_diff, if: ->(n) { n.line_code.present? }
  55 +
53 def self.create_status_change_note(noteable, project, author, status) 56 def self.create_status_change_note(noteable, project, author, status)
54 create({ 57 create({
55 noteable: noteable, 58 noteable: noteable,
@@ -67,28 +70,61 @@ class Note &lt; ActiveRecord::Base @@ -67,28 +70,61 @@ class Note &lt; ActiveRecord::Base
67 nil 70 nil
68 end 71 end
69 72
70 - def diff  
71 - if noteable.diffs.present?  
72 - noteable.diffs.select do |d|  
73 - if d.new_path  
74 - Digest::SHA1.hexdigest(d.new_path) == diff_file_index  
75 - end  
76 - end.first 73 + def find_diff
  74 + return nil unless noteable && noteable.diffs.present?
  75 +
  76 + @diff ||= noteable.diffs.find do |d|
  77 + Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path
77 end 78 end
78 end 79 end
79 80
  81 + def set_diff
  82 + # First lets find notes with same diff
  83 + # before iterating over all mr diffs
  84 + diff = Note.where(noteable_id: self.noteable_id, noteable_type: self.noteable_type, line_code: self.line_code).last.try(:diff)
  85 + diff ||= find_diff
  86 +
  87 + self.st_diff = diff.to_hash if diff
  88 + end
  89 +
  90 + def diff
  91 + @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
  92 + end
  93 +
  94 + def active?
  95 + # TODO: determine if discussion is outdated
  96 + # according to recent MR diff or not
  97 + true
  98 + end
  99 +
80 def diff_file_index 100 def diff_file_index
81 line_code.split('_')[0] 101 line_code.split('_')[0]
82 end 102 end
83 103
84 def diff_file_name 104 def diff_file_name
85 - diff.new_path 105 + diff.new_path if diff
  106 + end
  107 +
  108 + def diff_old_line
  109 + line_code.split('_')[1].to_i
86 end 110 end
87 111
88 def diff_new_line 112 def diff_new_line
89 line_code.split('_')[2].to_i 113 line_code.split('_')[2].to_i
90 end 114 end
91 115
  116 + def diff_line
  117 + return @diff_line if @diff_line
  118 +
  119 + if diff
  120 + Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old|
  121 + @diff_line = full_line if line_code == self.line_code
  122 + end
  123 + end
  124 +
  125 + @diff_line
  126 + end
  127 +
92 def discussion_id 128 def discussion_id
93 @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym 129 @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym
94 end 130 end
app/models/repository.rb
@@ -18,19 +18,25 @@ class Repository @@ -18,19 +18,25 @@ class Repository
18 end 18 end
19 19
20 def commit(id = nil) 20 def commit(id = nil)
21 - commit = raw_repository.commit(id) 21 + commit = Gitlab::Git::Commit.find(raw_repository, id)
22 commit = Commit.new(commit) if commit 22 commit = Commit.new(commit) if commit
23 commit 23 commit
24 end 24 end
25 25
26 def commits(ref, path = nil, limit = nil, offset = nil) 26 def commits(ref, path = nil, limit = nil, offset = nil)
27 - commits = raw_repository.commits(ref, path, limit, offset) 27 + commits = Gitlab::Git::Commit.where(
  28 + repo: raw_repository,
  29 + ref: ref,
  30 + path: path,
  31 + limit: limit,
  32 + offset: offset,
  33 + )
28 commits = Commit.decorate(commits) if commits.present? 34 commits = Commit.decorate(commits) if commits.present?
29 commits 35 commits
30 end 36 end
31 37
32 - def commits_between(target, source)  
33 - commits = raw_repository.commits_between(target, source) 38 + def commits_between(from, to)
  39 + commits = Gitlab::Git::Commit.between(raw_repository, from, to)
34 commits = Commit.decorate(commits) if commits.present? 40 commits = Commit.decorate(commits) if commits.present?
35 commits 41 commits
36 end 42 end
@@ -43,6 +49,12 @@ class Repository @@ -43,6 +49,12 @@ class Repository
43 tags.find { |tag| tag.name == name } 49 tags.find { |tag| tag.name == name }
44 end 50 end
45 51
  52 + def recent_branches(limit = 20)
  53 + branches.sort do |a, b|
  54 + a.commit.committed_date <=> b.commit.committed_date
  55 + end[0..limit]
  56 + end
  57 +
46 def add_branch(branch_name, ref) 58 def add_branch(branch_name, ref)
47 Rails.cache.delete(cache_key(:branch_names)) 59 Rails.cache.delete(cache_key(:branch_names))
48 60
app/services/notification_service.rb
@@ -102,19 +102,22 @@ class NotificationService @@ -102,19 +102,22 @@ class NotificationService
102 # ignore wall messages 102 # ignore wall messages
103 return true unless note.noteable_type.present? 103 return true unless note.noteable_type.present?
104 104
  105 + # ignore gitlab service messages
  106 + return true if note.note =~ /\A_Status changed to closed_/
  107 +
105 opts = { noteable_type: note.noteable_type, project_id: note.project_id } 108 opts = { noteable_type: note.noteable_type, project_id: note.project_id }
106 109
107 if note.commit_id.present? 110 if note.commit_id.present?
108 opts.merge!(commit_id: note.commit_id) 111 opts.merge!(commit_id: note.commit_id)
109 - recipients = [note.commit_author]  
110 else 112 else
111 opts.merge!(noteable_id: note.noteable_id) 113 opts.merge!(noteable_id: note.noteable_id)
112 - target = note.noteable  
113 - if target.respond_to?(:participants)  
114 - recipients = target.participants  
115 - else  
116 - recipients = []  
117 - end 114 + end
  115 +
  116 + target = note.noteable
  117 + if target.respond_to?(:participants)
  118 + recipients = target.participants
  119 + else
  120 + recipients = note.mentioned_users
118 end 121 end
119 122
120 # Get users who left comment in thread 123 # Get users who left comment in thread
app/views/admin/groups/edit.html.haml
@@ -4,22 +4,22 @@ @@ -4,22 +4,22 @@
4 - if @group.errors.any? 4 - if @group.errors.any?
5 .alert.alert-error 5 .alert.alert-error
6 %span= @group.errors.full_messages.first 6 %span= @group.errors.full_messages.first
7 - .clearfix.group_name_holder 7 + .control-group.group_name_holder
8 = f.label :name do 8 = f.label :name do
9 Group name is 9 Group name is
10 - .input  
11 - = f.text_field :name, placeholder: "Example Group", class: "xxlarge" 10 + .controls
  11 + = f.text_field :name, placeholder: "Example Group", class: "input-xxlarge"
12 12
13 - .clearfix.group-description-holder 13 + .control-group.group-description-holder
14 = f.label :description, "Details" 14 = f.label :description, "Details"
15 - .input  
16 - = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 15 + .controls
  16 + = f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
17 17
18 - .clearfix.group_name_holder 18 + .control-group.group_name_holder
19 = f.label :path do 19 = f.label :path do
20 %span.cred Group path is 20 %span.cred Group path is
21 - .input  
22 - = f.text_field :path, placeholder: "example-group", class: "xxlarge danger" 21 + .controls
  22 + = f.text_field :path, placeholder: "example-group", class: "input-xxlarge danger"
23 %ul.cred 23 %ul.cred
24 %li Changing group path can have unintended side effects. 24 %li Changing group path can have unintended side effects.
25 %li Renaming group path will rename directory for all related projects 25 %li Renaming group path will rename directory for all related projects
app/views/admin/groups/index.html.haml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 allows you to keep projects organized. 4 allows you to keep projects organized.
5 Use groups for uniting related projects. 5 Use groups for uniting related projects.
6 6
7 - = link_to 'New Group', new_admin_group_path, class: "btn btn-small pull-right" 7 + = link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right"
8 %br 8 %br
9 = form_tag admin_groups_path, method: :get, class: 'form-inline' do 9 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
10 = text_field_tag :name, params[:name], class: "span6" 10 = text_field_tag :name, params[:name], class: "span6"
app/views/admin/groups/new.html.haml
@@ -4,15 +4,15 @@ @@ -4,15 +4,15 @@
4 - if @group.errors.any? 4 - if @group.errors.any?
5 .alert.alert-error 5 .alert.alert-error
6 %span= @group.errors.full_messages.first 6 %span= @group.errors.full_messages.first
7 - .clearfix 7 + .control-group
8 = f.label :name do 8 = f.label :name do
9 Group name is 9 Group name is
10 - .input  
11 - = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"  
12 - .clearfix.group-description-holder 10 + .controls
  11 + = f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
  12 + .control-group.group-description-holder
13 = f.label :description, "Details" 13 = f.label :description, "Details"
14 - .input  
15 - = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 14 + .controls
  15 + = f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
16 16
17 .form-actions 17 .form-actions
18 = f.submit 'Create group', class: "btn btn-create" 18 = f.submit 'Create group', class: "btn btn-create"
app/views/admin/hooks/index.html.haml
@@ -10,10 +10,10 @@ @@ -10,10 +10,10 @@
10 .alert.alert-error 10 .alert.alert-error
11 - @hook.errors.full_messages.each do |msg| 11 - @hook.errors.full_messages.each do |msg|
12 %p= msg 12 %p= msg
13 - .clearfix 13 + .control-group
14 = f.label :url, "URL:" 14 = f.label :url, "URL:"
15 - .input  
16 - = f.text_field :url, class: "text_field xxlarge" 15 + .controls
  16 + = f.text_field :url, class: "text_field input-xxlarge input-xpadding"
17 &nbsp; 17 &nbsp;
18 = f.submit "Add System Hook", class: "btn btn-create" 18 = f.submit "Add System Hook", class: "btn btn-create"
19 %hr 19 %hr
app/views/admin/projects/index.html.haml
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 .title 38 .title
39 Projects (#{@projects.total_count}) 39 Projects (#{@projects.total_count})
40 .pull-right 40 .pull-right
41 - = link_to 'New Project', new_project_path, class: "btn btn-small btn-primary wide" 41 + = link_to 'New Project', new_project_path, class: "btn btn-new"
42 %ul.well-list 42 %ul.well-list
43 - @projects.each do |project| 43 - @projects.each do |project|
44 %li 44 %li
app/views/admin/users/_form.html.haml
@@ -8,28 +8,28 @@ @@ -8,28 +8,28 @@
8 8
9 %fieldset 9 %fieldset
10 %legend Account 10 %legend Account
11 - .clearfix 11 + .control-group
12 = f.label :name 12 = f.label :name
13 - .input 13 + .controls
14 = f.text_field :name, required: true, autocomplete: "off" 14 = f.text_field :name, required: true, autocomplete: "off"
15 %span.help-inline * required 15 %span.help-inline * required
16 - .clearfix 16 + .control-group
17 = f.label :username 17 = f.label :username
18 - .input 18 + .controls
19 = f.text_field :username, required: true, autocomplete: "off" 19 = f.text_field :username, required: true, autocomplete: "off"
20 %span.help-inline * required 20 %span.help-inline * required
21 - .clearfix 21 + .control-group
22 = f.label :email 22 = f.label :email
23 - .input 23 + .controls
24 = f.text_field :email, required: true, autocomplete: "off" 24 = f.text_field :email, required: true, autocomplete: "off"
25 %span.help-inline * required 25 %span.help-inline * required
26 26
27 - if @user.new_record? 27 - if @user.new_record?
28 %fieldset 28 %fieldset
29 %legend Password 29 %legend Password
30 - .clearfix 30 + .control-group
31 = f.label :password 31 = f.label :password
32 - .input 32 + .controls
33 %strong 33 %strong
34 A temporary password will be generated and sent to user. 34 A temporary password will be generated and sent to user.
35 %br 35 %br
@@ -37,33 +37,33 @@ @@ -37,33 +37,33 @@
37 - else 37 - else
38 %fieldset 38 %fieldset
39 %legend Password 39 %legend Password
40 - .clearfix 40 + .control-group
41 = f.label :password 41 = f.label :password
42 - .input= f.password_field :password, disabled: f.object.force_random_password  
43 - .clearfix 42 + .controls= f.password_field :password, disabled: f.object.force_random_password
  43 + .control-group
44 = f.label :password_confirmation 44 = f.label :password_confirmation
45 - .input= f.password_field :password_confirmation, disabled: f.object.force_random_password 45 + .controls= f.password_field :password_confirmation, disabled: f.object.force_random_password
46 46
47 %fieldset 47 %fieldset
48 %legend Access 48 %legend Access
49 .row 49 .row
50 .span8 50 .span8
51 - .clearfix 51 + .control-group
52 = f.label :projects_limit 52 = f.label :projects_limit
53 - .input= f.number_field :projects_limit 53 + .controls= f.number_field :projects_limit
54 54
55 - .clearfix 55 + .control-group
56 = f.label :can_create_group 56 = f.label :can_create_group
57 - .input= f.check_box :can_create_group 57 + .controls= f.check_box :can_create_group
58 58
59 - .clearfix 59 + .control-group
60 = f.label :can_create_team 60 = f.label :can_create_team
61 - .input= f.check_box :can_create_team 61 + .controls= f.check_box :can_create_team
62 62
63 - .clearfix 63 + .control-group
64 = f.label :admin do 64 = f.label :admin do
65 %strong.cred Administrator 65 %strong.cred Administrator
66 - .input= f.check_box :admin 66 + .controls= f.check_box :admin
67 .span4 67 .span4
68 - unless @user.new_record? 68 - unless @user.new_record?
69 .alert.alert-error 69 .alert.alert-error
@@ -75,17 +75,17 @@ @@ -75,17 +75,17 @@
75 = link_to 'Block User', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" 75 = link_to 'Block User', block_admin_user_path(@user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
76 %fieldset 76 %fieldset
77 %legend Profile 77 %legend Profile
78 - .clearfix 78 + .control-group
79 = f.label :skype 79 = f.label :skype
80 - .input= f.text_field :skype  
81 - .clearfix 80 + .controls= f.text_field :skype
  81 + .control-group
82 = f.label :linkedin 82 = f.label :linkedin
83 - .input= f.text_field :linkedin  
84 - .clearfix 83 + .controls= f.text_field :linkedin
  84 + .control-group
85 = f.label :twitter 85 = f.label :twitter
86 - .input= f.text_field :twitter 86 + .controls= f.text_field :twitter
87 87
88 - .actions 88 + .form-actions
89 - if @user.new_record? 89 - if @user.new_record?
90 = f.submit 'Create user', class: "btn btn-create" 90 = f.submit 'Create user', class: "btn btn-create"
91 = link_to 'Cancel', admin_users_path, class: "btn btn-cancel" 91 = link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
app/views/admin/users/index.html.haml
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 .title 30 .title
31 Users (#{@users.total_count}) 31 Users (#{@users.total_count})
32 .pull-right 32 .pull-right
33 - = link_to 'New User', new_admin_user_path, class: "btn btn-small wide btn-primary" 33 + = link_to 'New User', new_admin_user_path, class: "btn btn-new"
34 %ul.well-list 34 %ul.well-list
35 - @users.each do |user| 35 - @users.each do |user|
36 %li 36 %li
@@ -55,4 +55,4 @@ @@ -55,4 +55,4 @@
55 - else 55 - else
56 = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove" 56 = link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn btn-small btn-remove"
57 = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove" 57 = link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn btn-small btn-remove"
58 - = paginate @users, theme: "gitlab" 58 + = paginate @users, theme: "gitlab"
app/views/dashboard/_filter.html.haml
@@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
1 -= form_tag dashboard_filter_path(entity), method: 'get' do  
2 - %fieldset  
3 - %ul.nav.nav-pills.nav-stacked  
4 - %li{class: ("active" if !params[:status])}  
5 - = link_to dashboard_filter_path(entity, status: nil) do  
6 - Open  
7 - %li{class: ("active" if params[:status] == 'closed')}  
8 - = link_to dashboard_filter_path(entity, status: 'closed') do  
9 - Closed  
10 - %li{class: ("active" if params[:status] == 'all')}  
11 - = link_to dashboard_filter_path(entity, status: 'all') do  
12 - All  
13 -  
14 - %fieldset  
15 - %legend Projects:  
16 - %ul.nav.nav-pills.nav-stacked  
17 - - @projects.each do |project|  
18 - - unless entities_per_project(project, entity).zero?  
19 - %li{class: ("active" if params[:project_id] == project.id.to_s)}  
20 - = link_to dashboard_filter_path(entity, project_id: project.id) do  
21 - = project.name_with_namespace  
22 - %small.pull-right= entities_per_project(project, entity)  
23 -  
24 - %fieldset  
25 - %hr  
26 - = link_to "Reset", dashboard_filter_path(entity), class: 'btn pull-right'  
27 -  
app/views/dashboard/issues.html.haml
1 %h3.page-title 1 %h3.page-title
2 - Issues  
3 - %span.light  
4 - &ndash;  
5 - Assigned to you 2 + Issues assigned to me
6 %span.pull-right #{@issues.total_count} issues 3 %span.pull-right #{@issues.total_count} issues
7 4
  5 +%p.light
  6 + For all issues you should visit project issues page. Or you can use search panel to find specific issue
  7 +%hr
  8 +
8 .row 9 .row
9 .span3 10 .span3
10 - = render 'filter', entity: 'issue' 11 + = render 'shared/filter', entity: 'issue'
11 .span9 12 .span9
12 - - if @issues.any?  
13 - - @issues.group_by(&:project).each do |group|  
14 - %div.ui-box  
15 - - project = group[0]  
16 - .title  
17 - = link_to_project project  
18 - &nbsp;  
19 - %i.icon-angle-right  
20 - &nbsp;  
21 - = link_to 'issues', project_issues_path(project)  
22 -  
23 - %ul.well-list.issues-list  
24 - - group[1].each do |issue|  
25 - = render 'projects/issues/issue', issue: issue  
26 - %hr  
27 - = paginate @issues, theme: "gitlab"  
28 - - else  
29 - %p.nothing_here_message Nothing to show here 13 + = render 'shared/issues'
app/views/dashboard/merge_requests.html.haml
1 %h3.page-title 1 %h3.page-title
2 Merge Requests 2 Merge Requests
3 - %span.light  
4 - &ndash;  
5 - Authored by or assigned to you  
6 %span.pull-right #{@merge_requests.total_count} merge requests 3 %span.pull-right #{@merge_requests.total_count} merge requests
7 4
  5 +
  6 +%p.light
  7 + Only merge requests authored or assigned to you are listed here.
  8 +%hr
8 .row 9 .row
9 .span3 10 .span3
10 - = render 'filter', entity: 'merge_request' 11 + = render 'shared/filter', entity: 'merge_request'
11 .span9 12 .span9
12 = render 'shared/merge_requests' 13 = render 'shared/merge_requests'
app/views/dashboard/projects.html.haml
  1 +%h3.page-title My Projects
  2 +%p.light
  3 + All projects you have access to are listed here. Public projects are not included here unless you have membership in it
  4 +%hr
1 .row 5 .row
2 .span3 6 .span3
3 %ul.nav.nav-pills.nav-stacked 7 %ul.nav.nav-pills.nav-stacked
@@ -32,7 +36,7 @@ @@ -32,7 +36,7 @@
32 = label.name 36 = label.name
33 37
34 .span9 38 .span9
35 - %ul.bordered-list.my-projects 39 + %ul.bordered-list.my-projects.top-list
36 - @projects.each do |project| 40 - @projects.each do |project|
37 %li 41 %li
38 %h4.project-title 42 %h4.project-title
app/views/groups/_new_group_member.html.haml
1 = form_for @users_group, url: group_users_groups_path(@group) do |f| 1 = form_for @users_group, url: group_users_groups_path(@group) do |f|
2 %fieldset 2 %fieldset
3 - %legend= "New Group member(s) for #{@group.name}" 3 + %legend
  4 + New member(s) for
  5 + %strong #{@group.name}
  6 + group
4 7
5 - %h6 1. Choose users you want in the group  
6 - .clearfix 8 + %p 1. Choose users you want in the group
  9 + .control-group
7 = f.label :user_ids, "People" 10 = f.label :user_ids, "People"
8 - .input= users_select_tag(:user_ids, multiple: true, class: 'input-large') 11 + .controls= users_select_tag(:user_ids, multiple: true, class: 'input-large')
9 12
10 - %h6 2. Set access level for them  
11 - .clearfix 13 + %p 2. Set access level for them
  14 + .control-group
12 = f.label :group_access, "Group Access" 15 = f.label :group_access, "Group Access"
13 - .input= select_tag :group_access, options_for_select(UsersGroup.group_access_roles, @users_group.group_access), class: "project-access-select chosen" 16 + .controls= select_tag :group_access, options_for_select(UsersGroup.group_access_roles, @users_group.group_access), class: "project-access-select chosen"
14 17
15 .form-actions 18 .form-actions
16 = f.submit 'Add users into group', class: "btn btn-create" 19 = f.submit 'Add users into group', class: "btn btn-create"
app/views/groups/edit.html.haml
@@ -20,22 +20,22 @@ @@ -20,22 +20,22 @@
20 .ui-box 20 .ui-box
21 .title 21 .title
22 %strong= @group.name 22 %strong= @group.name
23 - Group Settings: 23 + group settings:
24 %div.form-holder 24 %div.form-holder
25 = form_for @group do |f| 25 = form_for @group do |f|
26 - if @group.errors.any? 26 - if @group.errors.any?
27 .alert.alert-error 27 .alert.alert-error
28 %span= @group.errors.full_messages.first 28 %span= @group.errors.full_messages.first
29 - .clearfix 29 + .control-group
30 = f.label :name do 30 = f.label :name do
31 Group name is 31 Group name is
32 - .input  
33 - = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 32 + .controls
  33 + = f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
34 34
35 - .clearfix.group-description-holder 35 + .control-group.group-description-holder
36 = f.label :description, "Details" 36 = f.label :description, "Details"
37 - .input  
38 - = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 37 + .controls
  38 + = f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
39 39
40 .form-actions 40 .form-actions
41 = f.submit 'Save group', class: "btn btn-save" 41 = f.submit 'Save group', class: "btn btn-save"
@@ -44,7 +44,7 @@ @@ -44,7 +44,7 @@
44 .ui-box 44 .ui-box
45 .title 45 .title
46 %strong= @group.name 46 %strong= @group.name
47 - Projects: 47 + projects:
48 - if can? current_user, :manage_group, @group 48 - if can? current_user, :manage_group, @group
49 %span.pull-right 49 %span.pull-right
50 = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny" do 50 = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny" do
@@ -85,4 +85,4 @@ @@ -85,4 +85,4 @@
85 %p 85 %p
86 %strong Removed group can not be restored! 86 %strong Removed group can not be restored!
87 87
88 - = link_to 'Remove Group', @group, confirm: 'Removed group can not be restored! Are you sure?', method: :delete, class: "btn btn-remove btn-small" 88 + = link_to 'Remove Group', @group, confirm: 'Removed group can not be restored! Are you sure?', method: :delete, class: "btn btn-remove"
app/views/groups/issues.html.haml
@@ -6,18 +6,6 @@ @@ -6,18 +6,6 @@
6 %hr 6 %hr
7 .row 7 .row
8 .span3 8 .span3
9 - = render 'filter', entity: 'issue' 9 + = render 'shared/filter', entity: 'issue'
10 .span9 10 .span9
11 - - if @issues.any?  
12 - - @issues.group_by(&:project).each do |group|  
13 - %div.ui-box  
14 - - project = group[0]  
15 - .title  
16 - = link_to_project project  
17 - %ul.well-list.issues-list  
18 - - group[1].each do |issue|  
19 - = render 'projects/issues/issue', issue: issue  
20 - %hr  
21 - = paginate @issues, theme: "gitlab"  
22 - - else  
23 - %p.nothing_here_message Nothing to show here 11 + = render 'shared/issues'
app/views/groups/members.html.haml
  1 +%h3.page-title
  2 + Group members
  3 +%p.light
  4 + Members of group have access to all group projects.
  5 +%hr
1 - can_manage_group = current_user.can? :manage_group, @group 6 - can_manage_group = current_user.can? :manage_group, @group
2 -.row  
3 - .span6  
4 - - if can_manage_group  
5 - = render "new_group_member"  
6 - - else  
7 - .light-well  
8 - %h4.nothing_here_message  
9 - Only group owners can manage group members  
10 - .span6  
11 - .ui-box  
12 - .title  
13 - %strong #{@group.name}  
14 - Group Members  
15 - %small  
16 - (#{@members.count})  
17 - %ul.well-list  
18 - - @members.each do |member|  
19 - = render 'users_groups/users_group', member: member, show_controls: can_manage_group  
20 - %p.light  
21 - Group members get access to all projects in this group 7 +.ui-box
  8 + .title
  9 + %strong #{@group.name}
  10 + group members
  11 + %small
  12 + (#{@members.count})
  13 + %ul.well-list
  14 + - @members.each do |member|
  15 + = render 'users_groups/users_group', member: member, show_controls: can_manage_group
  16 +- if can_manage_group
  17 + = render "new_group_member"
app/views/groups/merge_requests.html.haml
@@ -6,6 +6,6 @@ @@ -6,6 +6,6 @@
6 %hr 6 %hr
7 .row 7 .row
8 .span3 8 .span3
9 - = render 'filter', entity: 'merge_request' 9 + = render 'shared/filter', entity: 'merge_request'
10 .span9 10 .span9
11 = render 'shared/merge_requests' 11 = render 'shared/merge_requests'
app/views/groups/new.html.haml
@@ -2,19 +2,19 @@ @@ -2,19 +2,19 @@
2 - if @group.errors.any? 2 - if @group.errors.any?
3 .alert.alert-error 3 .alert.alert-error
4 %span= @group.errors.full_messages.first 4 %span= @group.errors.full_messages.first
5 - .clearfix 5 + .control-group
6 = f.label :name do 6 = f.label :name do
7 Group name is 7 Group name is
8 - .input  
9 - = f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left" 8 + .controls
  9 + = f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
10 10
11 - .clearfix.group-description-holder 11 + .control-group.group-description-holder
12 = f.label :description, "Details" 12 = f.label :description, "Details"
13 - .input  
14 - = f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4 13 + .controls
  14 + = f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
15 15
16 - .clearfix  
17 - .input 16 + .control-group
  17 + .controls
18 %ul 18 %ul
19 %li Group is kind of directory for several projects 19 %li Group is kind of directory for several projects
20 %li All created groups are private 20 %li All created groups are private
app/views/help/index.html.haml
@@ -8,8 +8,6 @@ @@ -8,8 +8,6 @@
8 %br 8 %br
9 Fast, secure and stable solution based on Ruby on Rails. 9 Fast, secure and stable solution based on Ruby on Rails.
10 10
11 -%br  
12 -  
13 .row 11 .row
14 .span4 12 .span4
15 .ui-box 13 .ui-box
app/views/notify/new_user_email.html.haml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 - if Gitlab.config.gitlab.signup_enabled 4 - if Gitlab.config.gitlab.signup_enabled
5 Your account has been created successfully. 5 Your account has been created successfully.
6 - else 6 - else
7 - The Administrator created an account for you. Now you are a member of company GitLab application. 7 + The Administrator created an account for you. Now you are a member of the company GitLab application.
8 %p 8 %p
9 login.......................................... 9 login..........................................
10 %code= @user['email'] 10 %code= @user['email']
app/views/notify/new_user_email.text.erb
1 Hi <%= @user.name %>! 1 Hi <%= @user.name %>!
2 2
3 -The Administrator created an account for you. Now you are a member of company GitLab application. 3 +The Administrator created an account for you. Now you are a member of the company GitLab application.
4 4
5 login.................. <%= @user.email %> 5 login.................. <%= @user.email %>
6 <% if @user.created_by_id %> 6 <% if @user.created_by_id %>
app/views/profiles/account.html.haml
  1 +%h3.page-title
  2 + Account settings
  3 +%p.light
  4 + You can change password, username, private token here.
  5 + - if current_user.ldap_user?
  6 + Some options are unavailable for LDAP accounts
  7 +%hr
1 - unless current_user.ldap_user? 8 - unless current_user.ldap_user?
2 - if Gitlab.config.omniauth.enabled 9 - if Gitlab.config.omniauth.enabled
3 %fieldset 10 %fieldset
@@ -20,15 +27,15 @@ @@ -20,15 +27,15 @@
20 - @user.errors.full_messages.each do |msg| 27 - @user.errors.full_messages.each do |msg|
21 %li= msg 28 %li= msg
22 29
23 - .clearfix 30 + .control-group
24 = f.label :password 31 = f.label :password
25 - .input= f.password_field :password, required: true  
26 - .clearfix 32 + .controls= f.password_field :password, required: true
  33 + .control-group
27 = f.label :password_confirmation 34 = f.label :password_confirmation
28 - .input 35 + .controls
29 = f.password_field :password_confirmation, required: true 36 = f.password_field :password_confirmation, required: true
30 - .clearfix  
31 - .input 37 + .control-group
  38 + .controls
32 = f.submit 'Save password', class: "btn btn-save" 39 = f.submit 'Save password', class: "btn btn-save"
33 40
34 41
@@ -47,7 +54,7 @@ @@ -47,7 +54,7 @@
47 It can be used for atom feed or API 54 It can be used for atom feed or API
48 %p.cgray 55 %p.cgray
49 - if current_user.private_token 56 - if current_user.private_token
50 - = text_field_tag "token", current_user.private_token, class: "xxlarge large_text" 57 + = text_field_tag "token", current_user.private_token, class: "input-xxlarge large_text input-xpadding"
51 = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token" 58 = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
52 - else 59 - else
53 %span You don`t have one yet. Click generate to fix it. 60 %span You don`t have one yet. Click generate to fix it.
@@ -63,7 +70,7 @@ @@ -63,7 +70,7 @@
63 = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f| 70 = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
64 .padded 71 .padded
65 = f.label :username 72 = f.label :username
66 - .input 73 + .controls
67 = f.text_field :username, required: true 74 = f.text_field :username, required: true
68 &nbsp; 75 &nbsp;
69 %span.loading-gif.hide= image_tag "ajax_loader.gif" 76 %span.loading-gif.hide= image_tag "ajax_loader.gif"
@@ -76,7 +83,7 @@ @@ -76,7 +83,7 @@
76 %ul.cred 83 %ul.cred
77 %li It will change web url for personal projects. 84 %li It will change web url for personal projects.
78 %li It will change the git path to repositories for personal projects. 85 %li It will change the git path to repositories for personal projects.
79 - .input 86 + .controls
80 = f.submit 'Save username', class: "btn btn-save" 87 = f.submit 'Save username', class: "btn btn-save"
81 88
82 - if gitlab_config.signup_enabled 89 - if gitlab_config.signup_enabled
app/views/profiles/design.html.haml
  1 +%h3.page-title
  2 + My appearance settings
  3 +%p.light
  4 + Appearance settings saved to your profile and available across all devices
  5 +%hr
  6 +
1 = form_for @user, url: profile_path, remote: true, method: :put do |f| 7 = form_for @user, url: profile_path, remote: true, method: :put do |f|
2 %fieldset.application-theme 8 %fieldset.application-theme
3 %legend 9 %legend
app/views/profiles/groups/index.html.haml
  1 +%h3.page-title
  2 + Group membership
  3 + - if current_user.can_create_group?
  4 + %span.pull-right
  5 + = link_to new_group_path, class: "btn btn-new" do
  6 + %i.icon-plus
  7 + New Group
  8 +%p.light
  9 + Members of group have access to all group projects.
  10 +%hr
1 .ui-box 11 .ui-box
2 .title 12 .title
3 %strong Groups 13 %strong Groups
4 - (#{@groups.count})  
5 - - if current_user.can_create_group?  
6 - %span.pull-right  
7 - = link_to new_group_path, class: "btn btn-small btn-primary" do  
8 - %i.icon-plus  
9 - New Group 14 + (#{@user_groups.count})
10 %ul.well-list 15 %ul.well-list
11 - - @groups.each do |group| 16 + - @user_groups.each do |user_group|
  17 + - group = user_group.group
12 %li 18 %li
13 .pull-right 19 .pull-right
14 - if can?(current_user, :manage_group, group) 20 - if can?(current_user, :manage_group, group)
@@ -23,4 +29,7 @@ @@ -23,4 +29,7 @@
23 = link_to group, class: 'group-name' do 29 = link_to group, class: 'group-name' do
24 = group.name 30 = group.name
25 31
26 -= paginate @groups 32 + as #{user_group.human_access}
  33 +
  34 +
  35 += paginate @user_groups
app/views/profiles/history.html.haml
  1 +%h3.page-title
  2 + Account history
  3 +%p.light
  4 + You can see all events authored by your account here
  5 +%hr
1 .profile_history 6 .profile_history
2 = render @events 7 = render @events
3 %hr 8 %hr
app/views/profiles/keys/_form.html.haml
@@ -6,18 +6,18 @@ @@ -6,18 +6,18 @@
6 - @key.errors.full_messages.each do |msg| 6 - @key.errors.full_messages.each do |msg|
7 %li= msg 7 %li= msg
8 8
9 - .clearfix 9 + .control-group
10 = f.label :title 10 = f.label :title
11 - .input= f.text_field :title  
12 - .clearfix 11 + .controls= f.text_field :title, class: "input-xlarge"
  12 + .control-group
13 = f.label :key 13 = f.label :key
14 - .input 14 + .controls
15 %p.light 15 %p.light
16 Paste your public key here. Read more about how generate it #{link_to "here", help_ssh_path} 16 Paste your public key here. Read more about how generate it #{link_to "here", help_ssh_path}
17 - = f.text_area :key, class: [:xxlarge, :thin_area] 17 + = f.text_area :key, class: "input-xxlarge thin_area"
18 18
19 19
20 - .actions 20 + .form-actions
21 = f.submit 'Add key', class: "btn btn-create" 21 = f.submit 'Add key', class: "btn btn-create"
22 = link_to "Cancel", profile_keys_path, class: "btn btn-cancel" 22 = link_to "Cancel", profile_keys_path, class: "btn btn-cancel"
23 23
app/views/profiles/keys/index.html.haml
  1 +%h3.page-title
  2 + My SSH keys
  3 + .pull-right
  4 + = link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new"
1 %p.light 5 %p.light
2 SSH key allows you to establish a secure connection between your computer and GitLab 6 SSH key allows you to establish a secure connection between your computer and GitLab
3 -%p.light 7 + %br
4 Before you can add ssh key you need to 8 Before you can add ssh key you need to
5 = link_to "generate it", help_ssh_path 9 = link_to "generate it", help_ssh_path
6 - 10 +%hr
7 11
8 12
9 .ui-box 13 .ui-box
10 .title 14 .title
11 SSH Keys (#{@keys.count}) 15 SSH Keys (#{@keys.count})
12 - .pull-right  
13 - = link_to "Add SSH Key", new_profile_key_path, class: "btn btn-small btn-primary"  
14 %ul.well-list#keys-table 16 %ul.well-list#keys-table
15 = render @keys 17 = render @keys
16 - if @keys.blank? 18 - if @keys.blank?
app/views/profiles/notifications/_settings.html.haml
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 .row 2 .row
3 .span4 3 .span4
4 %span 4 %span
  5 + = notification_icon(notification)
  6 +
5 - if membership.kind_of? UsersGroup 7 - if membership.kind_of? UsersGroup
6 = link_to membership.group.name, membership.group 8 = link_to membership.group.name, membership.group
7 - else 9 - else
app/views/profiles/notifications/show.html.haml
1 -%h3.page-title Setup your notification level  
2 -  
3 -%p.light  
4 - %strong Disabled  
5 - &ndash; You will not get any notifications via email 1 +%h3.page-title
  2 + Notifications settings
6 %p.light 3 %p.light
7 - %strong Participating  
8 - &ndash; You will receive only notifications from related resources(ex. from assigned issue or your commit)  
9 -%p.light  
10 - %strong Watch  
11 - &ndash; You will receive all notifications from projects in which you participate 4 + Application use email specified in your profile for notifications
12 %hr 5 %hr
  6 +.alert.alert-info
  7 + %p
  8 + %i.icon-circle.cred
  9 + %strong Disabled
  10 + &ndash; You will not get any notifications via email
  11 + %p
  12 + %i.icon-circle.cblue
  13 + %strong Participating
  14 + &ndash; You will receive only notifications from related resources(ex. from assigned issue or your commit)
  15 + %p
  16 + %i.icon-circle.cgreen
  17 + %strong Watch
  18 + &ndash; You will receive all notifications from projects in which you participate
13 19
14 .row 20 .row
15 .span4 21 .span4
16 - %h5 Global setting 22 + %h4
  23 + = notification_icon(@notification)
  24 + Global setting
17 .span7 25 .span7
18 = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do 26 = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
19 = hidden_field_tag :notification_type, 'global' 27 = hidden_field_tag :notification_type, 'global'
@@ -30,20 +38,21 @@ @@ -30,20 +38,21 @@
30 = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit' 38 = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit'
31 %span Watch 39 %span Watch
32 40
33 -%hr 41 +%br
34 = link_to '#', class: 'js-toggle-visibility-link' do 42 = link_to '#', class: 'js-toggle-visibility-link' do
35 - %h6.btn.btn-tiny 43 + %span.btn.btn-tiny
36 %i.icon-chevron-down 44 %i.icon-chevron-down
37 %span Advanced notifications settings 45 %span Advanced notifications settings
38 .js-toggle-visibility-container.hide 46 .js-toggle-visibility-container.hide
39 - %h5 Groups:  
40 - %ul.well-list 47 + %hr
  48 + %h4 Groups:
  49 + %ul.bordered-list
41 - @users_groups.each do |users_group| 50 - @users_groups.each do |users_group|
42 - notification = Notification.new(users_group) 51 - notification = Notification.new(users_group)
43 = render 'settings', type: 'group', membership: users_group, notification: notification 52 = render 'settings', type: 'group', membership: users_group, notification: notification
44 53
45 - %h5 Projects:  
46 - %ul.well-list 54 + %h4 Projects:
  55 + %ul.bordered-list
47 - @users_projects.each do |users_project| 56 - @users_projects.each do |users_project|
48 - notification = Notification.new(users_project) 57 - notification = Notification.new(users_project)
49 = render 'settings', type: 'project', membership: users_project, notification: notification 58 = render 'settings', type: 'project', membership: users_project, notification: notification
app/views/profiles/passwords/new.html.haml
@@ -10,13 +10,13 @@ @@ -10,13 +10,13 @@
10 - @user.errors.full_messages.each do |msg| 10 - @user.errors.full_messages.each do |msg|
11 %li= msg 11 %li= msg
12 12
13 - .clearfix 13 + .control-group
14 = f.label :password 14 = f.label :password
15 - .input= f.password_field :password, required: true  
16 - .clearfix 15 + .controls= f.password_field :password, required: true
  16 + .control-group
17 = f.label :password_confirmation 17 = f.label :password_confirmation
18 - .input 18 + .controls
19 = f.password_field :password_confirmation, required: true 19 = f.password_field :password_confirmation, required: true
20 - .clearfix  
21 - .input 20 + .control-group
  21 + .controls
22 = f.submit 'Set new password', class: "btn btn-create" 22 = f.submit 'Set new password', class: "btn btn-create"
app/views/profiles/show.html.haml
@@ -87,4 +87,4 @@ @@ -87,4 +87,4 @@
87 = link_to "Add Public Key", new_profile_key_path, class: "btn btn-small" 87 = link_to "Add Public Key", new_profile_key_path, class: "btn btn-small"
88 88
89 .form-actions 89 .form-actions
90 - = f.submit 'Save', class: "btn btn-save" 90 + = f.submit 'Save changes', class: "btn btn-save"
app/views/projects/blame/_head.html.haml
@@ -1,2 +0,0 @@ @@ -1,2 +0,0 @@
1 -%div.tree-ref-holder  
2 - = render 'shared/ref_switcher', destination: 'tree', path: params[:path]  
app/views/projects/blame/show.html.haml
1 -= render "head" 1 +%h3.page-title Blame view
2 2
3 #tree-holder.tree-holder 3 #tree-holder.tree-holder
4 - %ul.breadcrumb  
5 - %li  
6 - %i.icon-angle-right  
7 - = link_to project_tree_path(@project, @ref) do  
8 - = @project.name  
9 - - tree_breadcrumbs(@tree, 6) do |link|  
10 - \/  
11 - %li= link  
12 - .clear  
13 -  
14 .file-holder 4 .file-holder
15 .file-title 5 .file-title
16 %i.icon-file 6 %i.icon-file
17 %span.file_name 7 %span.file_name
18 - = @blob.name 8 + = @path
19 %small= number_to_human_size @blob.size 9 %small= number_to_human_size @blob.size
20 %span.options= render "projects/blob/actions" 10 %span.options= render "projects/blob/actions"
21 .file-content.blame 11 .file-content.blame
app/views/projects/blob/_actions.html.haml
1 .btn-group.tree-btn-group 1 .btn-group.tree-btn-group
2 -# only show edit link for text files 2 -# only show edit link for text files
3 - if @blob.text? 3 - if @blob.text?
4 - = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit?  
5 - = link_to "raw", project_raw_path(@project, @id), class: "btn btn-tiny", target: "_blank" 4 + = link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-small", disabled: !allowed_tree_edit?
  5 + = link_to "raw", project_raw_path(@project, @id), class: "btn btn-small", target: "_blank"
6 -# only show normal/blame view links for text files 6 -# only show normal/blame view links for text files
7 - if @blob.text? 7 - if @blob.text?
8 - if current_page? project_blame_path(@project, @id) 8 - if current_page? project_blame_path(@project, @id)
9 - = link_to "normal view", project_blob_path(@project, @id), class: "btn btn-tiny" 9 + = link_to "normal view", project_blob_path(@project, @id), class: "btn btn-small"
10 - else 10 - else
11 - = link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny" unless @blob.empty?  
12 - = link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny" 11 + = link_to "blame", project_blame_path(@project, @id), class: "btn btn-small" unless @blob.empty?
  12 + = link_to "history", project_commits_path(@project, @id), class: "btn btn-small"
app/views/projects/branches/_filter.html.haml 0 → 100644
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +%ul.nav.nav-pills.nav-stacked
  2 + = nav_link(path: 'branches#recent') do
  3 + = link_to 'Recent', recent_project_branches_path(@project)
  4 + = nav_link(path: 'protected_branches#index') do
  5 + = link_to project_protected_branches_path(@project) do
  6 + Protected
  7 + %i.icon-lock
  8 + = nav_link(path: 'branches#index') do
  9 + = link_to 'All branches', project_branches_path(@project)
  10 +
  11 +
  12 +%hr
  13 +- if can? current_user, :push_code, @project
  14 + = link_to new_project_branch_path(@project), class: 'btn btn-create' do
  15 + %i.icon-add-sign
  16 + New branch
  17 +
app/views/projects/branches/index.html.haml
1 = render "projects/commits/head" 1 = render "projects/commits/head"
2 .row 2 .row
3 .span3 3 .span3
4 - = render "projects/repositories/filter" 4 + = render "filter"
5 .span9 5 .span9
6 - unless @branches.empty? 6 - unless @branches.empty?
7 %ul.bordered-list 7 %ul.bordered-list
app/views/projects/branches/recent.html.haml 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 += render "projects/commits/head"
  2 +.row
  3 + .span3
  4 + = render "filter"
  5 + .span9
  6 + %ul.bordered-list
  7 + - @branches.each do |branch|
  8 + = render "projects/branches/branch", branch: branch
app/views/projects/commits/_head.html.haml
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 = link_to 'Compare', project_compare_index_path(@project) 7 = link_to 'Compare', project_compare_index_path(@project)
8 8
9 = nav_link(html_options: {class: branches_tab_class}) do 9 = nav_link(html_options: {class: branches_tab_class}) do
10 - = link_to project_repository_path(@project) do 10 + = link_to recent_project_branches_path(@project) do
11 Branches 11 Branches
12 %span.badge= @repository.branches.length 12 %span.badge= @repository.branches.length
13 13
app/views/projects/commits/_text_file.html.haml
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 %a.supp_diff_link Diff suppressed. Click to show 3 %a.supp_diff_link Diff suppressed. Click to show
4 4
5 %table.text-file{class: "#{'hide' if too_big}"} 5 %table.text-file{class: "#{'hide' if too_big}"}
6 - - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old| 6 + - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old, raw_line|
7 %tr.line_holder{ id: line_code, class: "#{type}" } 7 %tr.line_holder{ id: line_code, class: "#{type}" }
8 - if type == "match" 8 - if type == "match"
9 %td.old_line= "..." 9 %td.old_line= "..."
@@ -20,4 +20,4 @@ @@ -20,4 +20,4 @@
20 - if @reply_allowed 20 - if @reply_allowed
21 - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) 21 - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
22 - unless comments.empty? 22 - unless comments.empty?
23 - = render "projects/notes/diff_notes_with_reply", notes: comments 23 + = render "projects/notes/diff_notes_with_reply", notes: comments, line: line
app/views/projects/commits/show.html.haml
1 = render "head" 1 = render "head"
2 2
3 - if @path.present? 3 - if @path.present?
4 - %ul.breadcrumb 4 + %ul.breadcrumb.commit-breadcrumb
5 %li.light 5 %li.light
6 History for 6 History for
7 = commits_breadcrumbs 7 = commits_breadcrumbs
app/views/projects/compare/_form.html.haml
@@ -14,9 +14,9 @@ @@ -14,9 +14,9 @@
14 .pull-left 14 .pull-left
15 - if params[:to] && params[:from] 15 - if params[:to] && params[:from]
16 = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'} 16 = link_to 'switch', {from: params[:to], to: params[:from]}, {class: 'commits-compare-switch has_tooltip', title: 'Switch base of comparison'}
17 - = text_field_tag :from, params[:from], placeholder: "master", class: "xlarge" 17 + = text_field_tag :from, params[:from], placeholder: "master", class: "input-xlarge input-xpadding"
18 = "..." 18 = "..."
19 - = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge" 19 + = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "input-xlarge input-xpadding"
20 .pull-left 20 .pull-left
21 &nbsp; 21 &nbsp;
22 = submit_tag "Compare", class: "btn btn-create commits-compare-btn" 22 = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
app/views/projects/create.js.haml
@@ -4,5 +4,6 @@ @@ -4,5 +4,6 @@
4 - else 4 - else
5 :plain 5 :plain
6 $(".project-edit-errors").html("#{escape_javascript(render('errors'))}"); 6 $(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
  7 + $('.project-submit').enable();
7 $('.save-project-loader').hide(); 8 $('.save-project-loader').hide();
8 $('.project-edit-container').show(); 9 $('.project-edit-container').show();
app/views/projects/deploy_keys/_form.html.haml
@@ -6,18 +6,18 @@ @@ -6,18 +6,18 @@
6 - @key.errors.full_messages.each do |msg| 6 - @key.errors.full_messages.each do |msg|
7 %li= msg 7 %li= msg
8 8
9 - .clearfix 9 + .control-group
10 = f.label :title 10 = f.label :title
11 - .input= f.text_field :title  
12 - .clearfix 11 + .controls= f.text_field :title, class: 'input-xlarge'
  12 + .control-group
13 = f.label :key 13 = f.label :key
14 - .input  
15 - = f.text_area :key, class: [:xxlarge, :thin_area]  
16 - %p.hint 14 + .controls
  15 + %p.light
17 Paste a machine public key here. Read more about how generate it 16 Paste a machine public key here. Read more about how generate it
18 = link_to "here", help_ssh_path 17 = link_to "here", help_ssh_path
  18 + = f.text_area :key, class: "input-xxlarge thin_area"
19 19
20 - .actions 20 + .form-actions
21 = f.submit 'Create', class: "btn-create btn" 21 = f.submit 'Create', class: "btn-create btn"
22 = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel" 22 = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
23 23
app/views/projects/deploy_keys/index.html.haml
1 -%p.slead  
2 - Deploy keys allow read-only access to repository. They can be used for CI, staging or production servers 1 +%h3.page-title
  2 + Deploy keys allow read-only access to repository
3 3
4 -%p  
5 - You can create a deploy key or add existing one  
6 - = link_to new_project_deploy_key_path(@project), class: "btn btn-primary pull-right", title: "New Deploy Key" do 4 + = link_to new_project_deploy_key_path(@project), class: "btn btn-new pull-right", title: "New Deploy Key" do
7 %i.icon-plus 5 %i.icon-plus
8 New Deploy Key 6 New Deploy Key
9 7
  8 +%p.light
  9 + They can be used for CI, staging or production servers.
  10 + You can create a deploy key or add existing one
  11 +
10 %hr.clearfix 12 %hr.clearfix
11 13
12 .row 14 .row
13 .span5.enabled-keys 15 .span5.enabled-keys
14 - %h5.cgreen  
15 - Enabled deploy keys  
16 - %small for this project 16 + %h5
  17 + %strong.cgreen Enabled deploy keys
  18 + for this project
17 %ul.bordered-list 19 %ul.bordered-list
18 = render @enabled_keys 20 = render @enabled_keys
19 - if @enabled_keys.blank? 21 - if @enabled_keys.blank?
@@ -21,10 +23,10 @@ @@ -21,10 +23,10 @@
21 %p.nothing_here_message Create #{link_to 'new deploy key', new_project_deploy_key_path(@project)} or add existing one 23 %p.nothing_here_message Create #{link_to 'new deploy key', new_project_deploy_key_path(@project)} or add existing one
22 .span5.available-keys 24 .span5.available-keys
23 %h5 25 %h5
24 - Available deploy keys  
25 - %small from projects you are able to manage 26 + %strong Deploy keys
  27 + from projects available for you
26 %ul.bordered-list 28 %ul.bordered-list
27 = render @available_keys 29 = render @available_keys
28 - if @available_keys.blank? 30 - if @available_keys.blank?
29 .light-well 31 .light-well
30 - %p.nothing_here_message All deploy keys created in projects you own will be displayed here 32 + %p.nothing_here_message All deploy keys created in projects you participate will be displayed here
app/views/projects/edit.html.haml
@@ -4,28 +4,28 @@ @@ -4,28 +4,28 @@
4 .ui-box.white 4 .ui-box.white
5 .title 5 .title
6 %strong= @project.name 6 %strong= @project.name
7 - Project Settings: 7 + project settings:
8 .form-holder 8 .form-holder
9 = form_for(@project, remote: true) do |f| 9 = form_for(@project, remote: true) do |f|
10 %fieldset 10 %fieldset
11 - .clearfix.project_name_holder 11 + .control-group.project_name_holder
12 = f.label :name do 12 = f.label :name do
13 Project name is 13 Project name is
14 - .input 14 + .controls
15 = f.text_field :name, placeholder: "Example Project", class: "span5" 15 = f.text_field :name, placeholder: "Example Project", class: "span5"
16 16
17 17
18 - .clearfix 18 + .control-group
19 = f.label :description do 19 = f.label :description do
20 Project description 20 Project description
21 %span.light (optional) 21 %span.light (optional)
22 - .input 22 + .controls
23 = f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250 23 = f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250
24 24
25 - - unless @project.empty_repo?  
26 - .clearfix 25 + - if @project.repository.exists? && @project.repository.branch_names.any?
  26 + .control-group
27 = f.label :default_branch, "Default Branch" 27 = f.label :default_branch, "Default Branch"
28 - .input= f.select(:default_branch, @repository.branch_names, {}, {class: 'chosen'}) 28 + .controls= f.select(:default_branch, @repository.branch_names, {}, {class: 'chosen'})
29 29
30 30
31 - if can?(current_user, :change_public_mode, @project) 31 - if can?(current_user, :change_public_mode, @project)
@@ -66,11 +66,11 @@ @@ -66,11 +66,11 @@
66 - if Project.issues_tracker.values.count > 1 66 - if Project.issues_tracker.values.count > 1
67 .control-group 67 .control-group
68 = f.label :issues_tracker, "Issues tracker", class: 'control-label' 68 = f.label :issues_tracker, "Issues tracker", class: 'control-label'
69 - .input= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled }) 69 + .controls= f.select(:issues_tracker, Project.issues_tracker.values, {}, { disabled: !@project.issues_enabled })
70 70
71 - .clearfix 71 + .control-group
72 = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label' 72 = f.label :issues_tracker_id, "Project name or id in issues tracker", class: 'control-label'
73 - .input= f.text_field :issues_tracker_id, disabled: !@project.can_have_issues_tracker_id? 73 + .controls= f.text_field :issues_tracker_id, disabled: !@project.can_have_issues_tracker_id?
74 74
75 .control-group 75 .control-group
76 = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label' 76 = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
@@ -98,7 +98,7 @@ @@ -98,7 +98,7 @@
98 98
99 99
100 .form-actions 100 .form-actions
101 - = f.submit 'Save', class: "btn btn-save" 101 + = f.submit 'Save changes', class: "btn btn-save"
102 102
103 - if can?(current_user, :change_namespace, @project) 103 - if can?(current_user, :change_namespace, @project)
104 .ui-box.ui-box-danger 104 .ui-box.ui-box-danger
@@ -110,7 +110,7 @@ @@ -110,7 +110,7 @@
110 = f.label :namespace_id do 110 = f.label :namespace_id do
111 %span Namespace 111 %span Namespace
112 .controls 112 .controls
113 - .clearfix 113 + .control-group
114 = f.select :namespace_id, namespaces_options(@project.namespace_id), {prompt: 'Choose a project namespace'}, {class: 'chosen'} 114 = f.select :namespace_id, namespaces_options(@project.namespace_id), {prompt: 'Choose a project namespace'}, {class: 'chosen'}
115 %ul 115 %ul
116 %li Be careful. Changing project namespace can have unintended side effects 116 %li Be careful. Changing project namespace can have unintended side effects
@@ -130,7 +130,7 @@ @@ -130,7 +130,7 @@
130 = f.label :path do 130 = f.label :path do
131 %span Path 131 %span Path
132 .controls 132 .controls
133 - .clearfix 133 + .control-group
134 = f.text_field :path 134 = f.text_field :path
135 %ul 135 %ul
136 %li Be careful. Rename of project repo can have unintended side effects 136 %li Be careful. Rename of project repo can have unintended side effects
app/views/projects/edit_tree/show.html.haml
  1 +%h3.page-title Edit mode
1 .file-editor 2 .file-editor
2 = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do 3 = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
3 .file-holder 4 .file-holder
app/views/projects/hooks/index.html.haml
@@ -11,10 +11,10 @@ @@ -11,10 +11,10 @@
11 .alert.alert-error 11 .alert.alert-error
12 - @hook.errors.full_messages.each do |msg| 12 - @hook.errors.full_messages.each do |msg|
13 %p= msg 13 %p= msg
14 - .clearfix 14 + .control-group
15 = f.label :url, "URL:" 15 = f.label :url, "URL:"
16 - .input  
17 - = f.text_field :url, class: "text_field xxlarge" 16 + .controls
  17 + = f.text_field :url, class: "text_field input-xxlarge input-xpadding", placeholder: 'http://example.com/trigger-ci.json'
18 &nbsp; 18 &nbsp;
19 = f.submit "Add Web Hook", class: "btn btn-create" 19 = f.submit "Add Web Hook", class: "btn btn-create"
20 %hr 20 %hr
app/views/projects/issues/_filter.html.haml
@@ -18,6 +18,9 @@ @@ -18,6 +18,9 @@
18 All 18 All
19 19
20 %fieldset 20 %fieldset
21 - %hr  
22 - = link_to "Reset", project_issues_path(@project), class: 'btn pull-right' 21 + - if %w(status milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
  22 + = link_to project_issues_path(@project), class: 'cgray pull-right' do
  23 + %i.icon-remove
  24 + Clear filter
  25 +
23 26
app/views/projects/issues/_form.html.haml
@@ -8,18 +8,18 @@ @@ -8,18 +8,18 @@
8 %br 8 %br
9 .ui-box.ui-box-show 9 .ui-box.ui-box-show
10 .ui-box-head 10 .ui-box-head
11 - .clearfix 11 + .control-group
12 = f.label :title do 12 = f.label :title do
13 %strong= "Subject *" 13 %strong= "Subject *"
14 - .input  
15 - = f.text_field :title, maxlength: 255, class: "xxlarge js-gfm-input", autofocus: true, required: true 14 + .controls
  15 + = f.text_field :title, maxlength: 255, class: "input-xxlarge js-gfm-input", autofocus: true, required: true
16 .ui-box-body 16 .ui-box-body
17 - .clearfix 17 + .control-group
18 .issue_assignee.pull-left 18 .issue_assignee.pull-left
19 = f.label :assignee_id do 19 = f.label :assignee_id do
20 %i.icon-user 20 %i.icon-user
21 Assign to 21 Assign to
22 - .input 22 + .controls
23 .pull-left 23 .pull-left
24 = f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'}) 24 = f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
25 .pull-right 25 .pull-right
@@ -29,25 +29,25 @@ @@ -29,25 +29,25 @@
29 = f.label :milestone_id do 29 = f.label :milestone_id do
30 %i.icon-time 30 %i.icon-time
31 Milestone 31 Milestone
32 - .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) 32 + .controls= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
33 33
34 .ui-box-bottom 34 .ui-box-bottom
35 - .clearfix 35 + .control-group
36 = f.label :label_list do 36 = f.label :label_list do
37 %i.icon-tag 37 %i.icon-tag
38 Labels 38 Labels
39 - .input  
40 - = f.text_field :label_list, maxlength: 2000, class: "xxlarge" 39 + .controls
  40 + = f.text_field :label_list, maxlength: 2000, class: "input-xxlarge"
41 %p.hint Separate labels with commas. 41 %p.hint Separate labels with commas.
42 42
43 - .clearfix 43 + .control-group
44 = f.label :description, "Details" 44 = f.label :description, "Details"
45 - .input  
46 - = f.text_area :description, class: "xxlarge js-gfm-input", rows: 14 45 + .controls
  46 + = f.text_area :description, class: "input-xxlarge js-gfm-input", rows: 14
47 %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. 47 %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
48 48
49 49
50 - .actions 50 + .form-actions
51 - if @issue.new_record? 51 - if @issue.new_record?
52 = f.submit 'Submit new issue', class: "btn btn-create" 52 = f.submit 'Submit new issue', class: "btn btn-create"
53 -else 53 -else
app/views/projects/issues/index.html.haml
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 .pull-right 6 .pull-right
7 .span6 7 .span6
8 - if can? current_user, :write_issue, @project 8 - if can? current_user, :write_issue, @project
9 - = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-primary pull-right", title: "New Issue", id: "new_issue_link" do 9 + = link_to new_project_issue_path(@project, issue: { assignee_id: params[:assignee_id], milestone_id: params[:milestone_id]}), class: "btn btn-new pull-right", title: "New Issue", id: "new_issue_link" do
10 %i.icon-plus 10 %i.icon-plus
11 New Issue 11 New Issue
12 = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do 12 = form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 = hidden_field_tag :assignee_id, params[:assignee_id], id: 'search_assignee_id' 14 = hidden_field_tag :assignee_id, params[:assignee_id], id: 'search_assignee_id'
15 = hidden_field_tag :milestone_id, params[:milestone_id], id: 'search_milestone_id' 15 = hidden_field_tag :milestone_id, params[:milestone_id], id: 'search_milestone_id'
16 = hidden_field_tag :label_name, params[:label_name], id: 'search_label_name' 16 = hidden_field_tag :label_name, params[:label_name], id: 'search_label_name'
17 - = search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search input-xlarge append-right-10 search-text-input' } 17 + = search_field_tag :issue_search, nil, { placeholder: 'Filter by title or description', class: 'input-xpadding issue_search input-xlarge append-right-10 search-text-input' }
18 18
19 .row 19 .row
20 .span3 20 .span3
app/views/projects/merge_requests/_filter.html.haml
1 = form_tag project_issues_path(@project), method: 'get' do 1 = form_tag project_issues_path(@project), method: 'get' do
2 %fieldset 2 %fieldset
3 %ul.nav.nav-pills.nav-stacked 3 %ul.nav.nav-pills.nav-stacked
4 - %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}  
5 - = link_to project_merge_requests_path(@project, f: 'open', milestone_id: params[:milestone_id]) do 4 + %li{class: ("active" if (params[:status] == 'open' || !params[:status]))}
  5 + = link_to project_merge_requests_path(@project, status: 'open', milestone_id: params[:milestone_id]) do
6 Open 6 Open
7 - %li{class: ("active" if params[:f] == "closed")}  
8 - = link_to project_merge_requests_path(@project, f: "closed", milestone_id: params[:milestone_id]) do 7 + %li{class: ("active" if params[:status] == "closed")}
  8 + = link_to project_merge_requests_path(@project, status: "closed", milestone_id: params[:milestone_id]) do
9 Closed 9 Closed
10 - %li{class: ("active" if params[:f] == 'assigned-to-me')}  
11 - = link_to project_merge_requests_path(@project, f: 'assigned-to-me', milestone_id: params[:milestone_id]) do 10 + %li{class: ("active" if params[:status] == 'assigned-to-me')}
  11 + = link_to project_merge_requests_path(@project, status: 'assigned-to-me', milestone_id: params[:milestone_id]) do
12 Assigned To Me 12 Assigned To Me
13 - %li{class: ("active" if params[:f] == 'all')}  
14 - = link_to project_merge_requests_path(@project, f: 'all', milestone_id: params[:milestone_id]) do 13 + %li{class: ("active" if params[:status] == 'all')}
  14 + = link_to project_merge_requests_path(@project, status: 'all', milestone_id: params[:milestone_id]) do
15 All 15 All
16 16
17 %fieldset 17 %fieldset
18 - %hr  
19 - = link_to "Reset", project_merge_requests_path(@project), class: 'btn pull-right'  
20 - 18 + - if %w(status milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
  19 + = link_to project_merge_requests_path(@project), class: 'cgray pull-right' do
  20 + %i.icon-remove
  21 + Clear filter
app/views/projects/merge_requests/_form.html.haml
@@ -33,21 +33,21 @@ @@ -33,21 +33,21 @@
33 %i.icon-paper-clip 33 %i.icon-paper-clip
34 Details 34 Details
35 .merge-request-form-info 35 .merge-request-form-info
36 - .clearfix 36 + .control-group
37 = f.label :title do 37 = f.label :title do
38 %strong= "Title *" 38 %strong= "Title *"
39 - .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true  
40 - .clearfix 39 + .controls= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true
  40 + .control-group
41 .left 41 .left
42 = f.label :assignee_id do 42 = f.label :assignee_id do
43 %i.icon-user 43 %i.icon-user
44 Assign to 44 Assign to
45 - .input= f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'}) 45 + .controls= f.select(:assignee_id, @project.team.members.sort_by(&:name).map {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
46 .left 46 .left
47 = f.label :milestone_id do 47 = f.label :milestone_id do
48 %i.icon-time 48 %i.icon-time
49 Milestone 49 Milestone
50 - .input= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'}) 50 + .controls= f.select(:milestone_id, @project.milestones.active.all.map {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
51 51
52 .form-actions 52 .form-actions
53 - if @merge_request.new_record? 53 - if @merge_request.new_record?
app/views/projects/merge_requests/edit.html.haml
1 %h3.page-title 1 %h3.page-title
2 - = "Edit merge request #{@merge_request.id}" 2 + = "Edit merge request ##{@merge_request.id}"
3 %hr 3 %hr
4 = render 'form' 4 = render 'form'
app/views/projects/merge_requests/index.html.haml
1 - if can? current_user, :write_merge_request, @project 1 - if can? current_user, :write_merge_request, @project
2 - = link_to new_project_merge_request_path(@project), class: "pull-right btn btn-primary", title: "New Merge Request" do 2 + = link_to new_project_merge_request_path(@project), class: "pull-right btn btn-new", title: "New Merge Request" do
3 %i.icon-plus 3 %i.icon-plus
4 New Merge Request 4 New Merge Request
5 %h3.page-title 5 %h3.page-title
app/views/projects/merge_requests/show/_how_to_merge.html.haml
1 %div#modal_merge_info.modal.hide 1 %div#modal_merge_info.modal.hide
2 .modal-header 2 .modal-header
3 - %a.close{href: "#"} ×  
4 - %h3 How To Merge 3 + %a.close{href: "#", "data-dismiss" => "modal"} ×
  4 + %h3 How to merge
5 .modal-body 5 .modal-body
6 - if @merge_request.for_fork? 6 - if @merge_request.for_fork?
7 - source_remote = @merge_request.source_project.namespace.nil? ? "source" :@merge_request.source_project.namespace.path 7 - source_remote = @merge_request.source_project.namespace.nil? ? "source" :@merge_request.source_project.namespace.path
app/views/projects/merge_requests/show/_mr_accept.html.haml
@@ -11,7 +11,8 @@ @@ -11,7 +11,8 @@
11 %p 11 %p
12 You can accept this request automatically. 12 You can accept this request automatically.
13 If you still want to do it manually - 13 If you still want to do it manually -
14 - %strong= link_to "click here", "#", class: "how_to_merge_link vlink", title: "How To Merge" 14 + %strong
  15 + = link_to "click here", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
15 for instructions 16 for instructions
16 .accept_group 17 .accept_group
17 = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request" 18 = f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
@@ -31,7 +32,7 @@ @@ -31,7 +32,7 @@
31 .automerge_widget.cannot_be_merged{style: "display:none"} 32 .automerge_widget.cannot_be_merged{style: "display:none"}
32 .alert.alert-disabled 33 .alert.alert-disabled
33 %span 34 %span
34 - = link_to "Show how to merge", "#", class: "how_to_merge_link btn btn-small padded", title: "How To Merge" 35 + = link_to "Show how to merge", "#modal_merge_info", class: "how_to_merge_link btn btn-small padded", title: "How To Merge", "data-toggle" => "modal"
35 &nbsp; 36 &nbsp;
36 %strong This request can't be merged with GitLab. You should do it manually 37 %strong This request can't be merged with GitLab. You should do it manually
37 38
app/views/projects/milestones/_form.html.haml
@@ -26,13 +26,13 @@ @@ -26,13 +26,13 @@
26 .span6 26 .span6
27 .control-group 27 .control-group
28 = f.label :due_date, "Due Date", class: "control-label" 28 = f.label :due_date, "Due Date", class: "control-label"
29 - .input= f.hidden_field :due_date 29 + .controls= f.hidden_field :due_date
30 .controls 30 .controls
31 .datepicker 31 .datepicker
32 32
33 .form-actions 33 .form-actions
34 - if @milestone.new_record? 34 - if @milestone.new_record?
35 - = f.submit 'Create milestone', class: "btn-save btn" 35 + = f.submit 'Create milestone', class: "btn-create btn"
36 = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel" 36 = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
37 -else 37 -else
38 = f.submit 'Save changes', class: "btn-save btn" 38 = f.submit 'Save changes', class: "btn-save btn"
app/views/projects/milestones/_milestone.html.haml
@@ -4,8 +4,7 @@ @@ -4,8 +4,7 @@
4 = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do 4 = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
5 %i.icon-edit 5 %i.icon-edit
6 Edit 6 Edit
7 - - if milestone.can_be_closed?  
8 - = link_to 'Close', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-remove" 7 + = link_to 'Close Milestone', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-remove"
9 %h4 8 %h4
10 = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone) 9 = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
11 - if milestone.expired? and not milestone.closed? 10 - if milestone.expired? and not milestone.closed?
app/views/projects/milestones/index.html.haml
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 %h3.page-title 3 %h3.page-title
4 Milestones 4 Milestones
5 - if can? current_user, :admin_milestone, @project 5 - if can? current_user, :admin_milestone, @project
6 - = link_to new_project_milestone_path(@project), class: "pull-right btn btn-primary", title: "New Milestone" do 6 + = link_to new_project_milestone_path(@project), class: "pull-right btn btn-new", title: "New Milestone" do
7 %i.icon-plus 7 %i.icon-plus
8 New Milestone 8 New Milestone
9 9
app/views/projects/milestones/show.html.haml
1 = render "projects/issues/head" 1 = render "projects/issues/head"
2 -.row  
3 - .span6  
4 - %h3.page-title  
5 - Milestone ##{@milestone.id}  
6 - %small  
7 - = @milestone.expires_at  
8 - .back-link  
9 - = link_to project_milestones_path(@project) do  
10 - &larr; To milestones list  
11 - .span6  
12 - .pull-right  
13 - - unless @milestone.closed?  
14 - = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do  
15 - %i.icon-plus  
16 - New Issue  
17 - = link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn edit-milestone-link small grouped"  
18 - - if can?(current_user, :admin_milestone, @project)  
19 - = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-small grouped" do  
20 - %i.icon-edit  
21 - Edit 2 +%h3.page-title
  3 + Milestone ##{@milestone.id}
  4 + %small
  5 + = @milestone.expires_at
  6 + .pull-right
  7 + - if can?(current_user, :admin_milestone, @project)
  8 + = link_to edit_project_milestone_path(@project, @milestone), class: "btn grouped" do
  9 + %i.icon-edit
  10 + Edit
  11 + = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-remove"
22 12
  13 +- if @milestone.issues.any? && @milestone.can_be_closed?
  14 + .alert.alert-success
  15 + %span All issues for this milestone are closed. You may close milestone now.
23 16
  17 +.back-link
  18 + = link_to project_milestones_path(@project) do
  19 + &larr; To milestones list
24 20
25 -- if @milestone.can_be_closed?  
26 - %hr  
27 - %p  
28 - %span All issues for this milestone are closed. You may close milestone now.  
29 - = link_to 'Close Milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-remove"  
30 21
31 .ui-box.ui-box-show 22 .ui-box.ui-box-show
32 .ui-box-head 23 .ui-box-head
@@ -69,6 +60,11 @@ @@ -69,6 +60,11 @@
69 Participants 60 Participants
70 %span.badge= @users.count 61 %span.badge= @users.count
71 62
  63 + .pull-right
  64 + = link_to new_project_issue_path(@project, issue: { milestone_id: @milestone.id }), class: "btn btn-small grouped", title: "New Issue" do
  65 + %i.icon-plus
  66 + New Issue
  67 + = link_to 'Browse Issues', project_issues_path(@milestone.project, milestone_id: @milestone.id), class: "btn btn-small edit-milestone-link grouped"
72 68
73 .tab-content 69 .tab-content
74 .tab-pane.active#tab-issues 70 .tab-pane.active#tab-issues
app/views/projects/network/_head.html.haml
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 .control-group 15 .control-group
16 = label_tag :search , "Looking for commit:", class: 'control-label light' 16 = label_tag :search , "Looking for commit:", class: 'control-label light'
17 .controls 17 .controls
18 - = text_field_tag :q, @options[:q], placeholder: "Input SHA", class: "search-input xlarge" 18 + = text_field_tag :q, @options[:q], placeholder: "Input SHA", class: "search-input input-xlarge"
19 = button_tag type: 'submit', class: 'btn vtop' do 19 = button_tag type: 'submit', class: 'btn vtop' do
20 %i.icon-search 20 %i.icon-search
21 - @options.each do |key, value| 21 - @options.each do |key, value|
app/views/projects/new.html.haml
1 -.project-edit-container 1 +%p.slead
  2 + New projects are private by default. You choose who can see the project and commit to repository.
  3 +%hr
  4 +.project-edit-container.prepend-top-10
2 .project-edit-errors 5 .project-edit-errors
3 = render 'projects/errors' 6 = render 'projects/errors'
4 .project-edit-content 7 .project-edit-content
5 = form_for @project, remote: true do |f| 8 = form_for @project, remote: true do |f|
6 - .clearfix.project_name_holder 9 + .control-group.project_name_holder
7 = f.label :name do 10 = f.label :name do
8 - Project name is  
9 - .input  
10 - = f.text_field :name, placeholder: "Example Project", class: "xxlarge", tabindex: 1, autofocus: true  
11 - = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 11 + %strong Project name is
  12 + .controls
  13 + = f.text_field :name, placeholder: "Example Project", class: "input-xlarge", tabindex: 1, autofocus: true
12 14
13 - if current_user.can_select_namespace? 15 - if current_user.can_select_namespace?
14 - .clearfix 16 + .control-group
15 = f.label :namespace_id do 17 = f.label :namespace_id do
16 %span Namespace 18 %span Namespace
17 - .input 19 + .controls
18 = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen', tabindex: 2} 20 = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen', tabindex: 2}
19 21
20 - .clearfix  
21 - .input 22 + .control-group
  23 + .controls
22 = link_to "#", class: 'appear-link' do 24 = link_to "#", class: 'appear-link' do
23 %i.icon-upload-alt 25 %i.icon-upload-alt
24 %span Import existing repository? 26 %span Import existing repository?
25 - .clearfix.appear-data.import-url-data 27 + .control-group.appear-data.import-url-data
26 = f.label :import_url do 28 = f.label :import_url do
27 %span Import existing repo 29 %span Import existing repo
28 - .input  
29 - = f.text_field :import_url, class: 'xlarge', placeholder: 'https://github.com/randx/six.git' 30 + .controls
  31 + = f.text_field :import_url, class: 'input-xlarge', placeholder: 'https://github.com/randx/six.git'
30 .light 32 .light
31 URL must be cloneable 33 URL must be cloneable
32 - .clearfix 34 + .control-group
33 = f.label :description do 35 = f.label :description do
34 Description 36 Description
35 %span.light (optional) 37 %span.light (optional)
36 - .input  
37 - = f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250, tabindex: 3 38 + .controls
  39 + = f.text_area :description, placeholder: "awesome project", class: "input-xlarge", rows: 3, maxlength: 250, tabindex: 3
38 40
39 - %p.padded  
40 - New projects are private by default. You choose who can see the project and commit to repository.  
41 - %hr 41 + .form-actions
  42 + = f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
42 43
43 - - if current_user.can_create_group?  
44 - .clearfix  
45 - .input.light  
46 - Need a group for several dependent projects?  
47 - = link_to new_group_path, class: "btn btn-tiny" do  
48 - Create a group 44 + - if current_user.can_create_group?
  45 + .pull-right
  46 + .controls.light
  47 + Need a group for several dependent projects?
  48 + = link_to new_group_path, class: "btn btn-tiny" do
  49 + Create a group
49 50
50 .save-project-loader.hide 51 .save-project-loader.hide
51 %center 52 %center
app/views/projects/notes/_diff_notes_with_reply.html.haml
1 - note = notes.first # example note 1 - note = notes.first # example note
2 -%tr.notes_holder  
3 - %td.notes_line{ colspan: 2 }  
4 - %span.btn.disabled  
5 - %i.icon-comment  
6 - = notes.count  
7 - %td.notes_content  
8 - %ul.notes{ rel: note.discussion_id }  
9 - = render notes 2 +-# Check if line want not changed since comment was left
  3 +- if !defined?(line) || line == note.diff_line
  4 + %tr.notes_holder
  5 + %td.notes_line{ colspan: 2 }
  6 + %span.btn.disabled
  7 + %i.icon-comment
  8 + = notes.count
  9 + %td.notes_content
  10 + %ul.notes{ rel: note.discussion_id }
  11 + = render notes
10 12
11 - = render "projects/notes/discussion_reply_button", note: note 13 + = render "projects/notes/discussion_reply_button", note: note
app/views/projects/notes/_discussion.html.haml
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 ago 36 ago
37 .discussion-body 37 .discussion-body
38 - if note.for_diff_line? 38 - if note.for_diff_line?
39 - - if note.diff 39 + - if note.active?
40 .content 40 .content
41 .file= render "projects/notes/discussion_diff", discussion_notes: discussion_notes, note: note 41 .file= render "projects/notes/discussion_diff", discussion_notes: discussion_notes, note: note
42 - else 42 - else
app/views/projects/notes/_note.html.haml
@@ -8,8 +8,11 @@ @@ -8,8 +8,11 @@
8 - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) 8 - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
9 = link_to "#", title: "Edit comment", class: "js-note-edit" do 9 = link_to "#", title: "Edit comment", class: "js-note-edit" do
10 %i.icon-edit 10 %i.icon-edit
  11 + Edit
  12 + &nbsp;
11 = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure you want to remove this comment?', remote: true, class: "danger js-note-delete" do 13 = link_to project_note_path(@project, note), title: "Remove comment", method: :delete, confirm: 'Are you sure you want to remove this comment?', remote: true, class: "danger js-note-delete" do
12 %i.icon-trash.cred 14 %i.icon-trash.cred
  15 + Remove
13 = image_tag gravatar_icon(note.author_email), class: "avatar s32" 16 = image_tag gravatar_icon(note.author_email), class: "avatar s32"
14 = link_to_member(@project, note.author, avatar: false) 17 = link_to_member(@project, note.author, avatar: false)
15 %span.note-last-update 18 %span.note-last-update
app/views/projects/protected_branches/index.html.haml
1 = render "projects/commits/head" 1 = render "projects/commits/head"
2 .row 2 .row
3 .span3 3 .span3
4 - = render "projects/repositories/filter" 4 + = render "projects/branches/filter"
5 .span9 5 .span9
6 .alert.alert-info 6 .alert.alert-info
7 %p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}. 7 %p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}.
app/views/projects/repositories/_filter.html.haml
@@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
1 -%ul.nav.nav-pills.nav-stacked  
2 - = nav_link(path: 'repositories#show') do  
3 - = link_to 'Recent', project_repository_path(@project)  
4 - = nav_link(path: 'protected_branches#index') do  
5 - = link_to project_protected_branches_path(@project) do  
6 - Protected  
7 - %i.icon-lock  
8 - = nav_link(path: 'branches#index') do  
9 - = link_to 'All branches', project_branches_path(@project)  
10 -  
11 -  
12 -%hr  
13 -- if can? current_user, :push_code, @project  
14 - = link_to new_project_branch_path(@project), class: 'btn btn-create' do  
15 - %i.icon-add-sign  
16 - New branch  
17 -  
app/views/projects/repositories/show.html.haml
@@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
1 -= render "projects/commits/head"  
2 -.row  
3 - .span3  
4 - = render "filter"  
5 - .span9  
6 - %ul.bordered-list  
7 - - @activities.each do |update|  
8 - = render "projects/branches/branch", branch: update.head  
9 -  
app/views/projects/snippets/_form.html.haml
@@ -9,16 +9,16 @@ @@ -9,16 +9,16 @@
9 - @snippet.errors.full_messages.each do |msg| 9 - @snippet.errors.full_messages.each do |msg|
10 %li= msg 10 %li= msg
11 11
12 - .clearfix 12 + .control-group
13 = f.label :title 13 = f.label :title
14 - .input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true  
15 - .clearfix 14 + .controls= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
  15 + .control-group
16 = f.label "Lifetime" 16 = f.label "Lifetime"
17 - .input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}  
18 - .clearfix 17 + .controls= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
  18 + .control-group
19 .file-editor 19 .file-editor
20 = f.label :file_name, "File" 20 = f.label :file_name, "File"
21 - .input 21 + .controls
22 .file-holder.snippet 22 .file-holder.snippet
23 .file-title 23 .file-title
24 = f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true 24 = f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true
app/views/projects/team_members/_form.html.haml
@@ -9,16 +9,16 @@ @@ -9,16 +9,16 @@
9 %li= msg 9 %li= msg
10 10
11 %h6 1. Choose people you want in the team 11 %h6 1. Choose people you want in the team
12 - .clearfix 12 + .control-group
13 = f.label :user_ids, "People" 13 = f.label :user_ids, "People"
14 - .input 14 + .controls
15 = users_select_tag(:user_ids, multiple: true) 15 = users_select_tag(:user_ids, multiple: true)
16 16
17 %h6 2. Set access level for them 17 %h6 2. Set access level for them
18 - .clearfix 18 + .control-group
19 = f.label :project_access, "Project Access" 19 = f.label :project_access, "Project Access"
20 - .input= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen" 20 + .controls= select_tag :project_access, options_for_select(Project.access_options, @user_project_relation.project_access), class: "project-access-select chosen"
21 21
22 - .actions 22 + .form-actions
23 = f.submit 'Add users', class: "btn btn-create" 23 = f.submit 'Add users', class: "btn btn-create"
24 = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel" 24 = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
app/views/projects/team_members/_group_members.html.haml
1 .ui-box 1 .ui-box
2 .title 2 .title
3 - %strong #{@group.name} Group  
4 - members (#{@group.users_groups.count}) 3 + %strong #{@group.name}
  4 + group members (#{@group.users_groups.count})
5 .pull-right 5 .pull-right
6 = link_to members_group_path(@group), class: 'btn btn-small' do 6 = link_to members_group_path(@group), class: 'btn btn-small' do
7 %i.icon-edit 7 %i.icon-edit
app/views/projects/team_members/_team.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 - can_admin_project = (can? current_user, :admin_project, @project) 2 - can_admin_project = (can? current_user, :admin_project, @project)
3 .ui-box 3 .ui-box
4 .title 4 .title
5 - %strong #{@project.name} Project  
6 - members (#{members.count}) 5 + %strong #{@project.name}
  6 + project members (#{members.count})
7 %ul.well-list 7 %ul.well-list
8 - members.each do |team_member| 8 - members.each do |team_member|
9 = render 'team_member', member: team_member, current_user_can_admin_project: can_admin_project 9 = render 'team_member', member: team_member, current_user_can_admin_project: can_admin_project
app/views/projects/team_members/import.html.haml
1 %h3.page-title 1 %h3.page-title
2 - = "Import team from another project" 2 + = "Import members from another project"
  3 +%p.light
  4 + Only project members will be improted. Group members will be skipped.
3 %hr 5 %hr
4 -%p.slead  
5 - Read more about project team import #{link_to "here", '#', class: 'vlink'}.  
6 = form_tag apply_import_project_team_members_path(@project), method: 'post' do 6 = form_tag apply_import_project_team_members_path(@project), method: 'post' do
7 - %p.slead Choose project you want to use as team source:  
8 .padded 7 .padded
9 = label_tag :source_project_id, "Project" 8 = label_tag :source_project_id, "Project"
10 - .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true) 9 + .controls= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
11 10
12 - .actions  
13 - = submit_tag 'Import', class: "btn btn-save" 11 + .form-actions
  12 + = submit_tag 'Import project members', class: "btn btn-create"
14 = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel" 13 = link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
15 14
app/views/projects/team_members/index.html.haml
@@ -3,14 +3,14 @@ @@ -3,14 +3,14 @@
3 3
4 - if can? current_user, :admin_team_member, @project 4 - if can? current_user, :admin_team_member, @project
5 %span.pull-right 5 %span.pull-right
6 - = link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" do  
7 - Import team from another project  
8 - = link_to new_project_team_member_path(@project), class: "btn btn-primary small grouped", title: "New Team Member" do 6 + = link_to new_project_team_member_path(@project), class: "btn btn-new grouped", title: "New Team Member" do
9 New Team Member 7 New Team Member
  8 + = link_to import_project_team_members_path(@project), class: "btn grouped", title: "Import team from another project" do
  9 + Import members
10 10
11 %p.light 11 %p.light
12 Read more about project permissions 12 Read more about project permissions
13 %strong= link_to "here", help_permissions_path, class: "vlink" 13 %strong= link_to "here", help_permissions_path, class: "vlink"
  14 += render "team", members: @users_projects
14 - if @group 15 - if @group
15 = render "group_members" 16 = render "group_members"
16 -= render "team", members: @users_projects  
app/views/projects/wikis/_form.html.haml
@@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
15 = f.select :format, options_for_select(GollumWiki::MARKUPS, {selected: @wiki.format}), {}, class: "pull-right input-medium" 15 = f.select :format, options_for_select(GollumWiki::MARKUPS, {selected: @wiki.format}), {}, class: "pull-right input-medium"
16 = f.label :format, class: "pull-right", style: "padding-right: 20px;" 16 = f.label :format, class: "pull-right", style: "padding-right: 20px;"
17 .ui-box-body 17 .ui-box-body
18 - .input 18 + .controls
19 %span.cgray 19 %span.cgray
20 Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. 20 Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
21 To link to a (new) page you can just type 21 To link to a (new) page you can just type
@@ -23,14 +23,17 @@ @@ -23,14 +23,17 @@
23 \. 23 \.
24 24
25 .ui-box-bottom 25 .ui-box-bottom
26 - = f.label :content  
27 - .input= f.text_area :content, class: 'span8 js-gfm-input' 26 + .control-group
  27 + = f.label :content
  28 + .controls= f.text_area :content, class: 'span8 js-gfm-input'
28 .ui-box-bottom 29 .ui-box-bottom
29 - = f.label :commit_message  
30 - .input= f.text_field :message, class: 'span8'  
31 - .actions  
32 - = f.submit 'Save', class: "btn-save btn" 30 + .control-group
  31 + = f.label :commit_message
  32 + .controls= f.text_field :message, class: 'span8'
  33 + .form-actions
33 - if @wiki && @wiki.persisted? 34 - if @wiki && @wiki.persisted?
  35 + = f.submit 'Save changes', class: "btn-save btn"
34 = link_to "Cancel", project_wiki_path(@project, @wiki), class: "btn btn-cancel" 36 = link_to "Cancel", project_wiki_path(@project, @wiki), class: "btn btn-cancel"
35 - else 37 - else
  38 + = f.submit 'Create page', class: "btn-create btn"
36 = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel" 39 = link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel"
app/views/projects/wikis/_nav.html.haml
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 12
13 - if can?(current_user, :write_wiki, @project) 13 - if can?(current_user, :write_wiki, @project)
14 .pull-right 14 .pull-right
15 - = link_to '#', class: "add-new-wiki btn btn-small btn-primary" do 15 + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do
16 %i.icon-plus 16 %i.icon-plus
17 New Page 17 New Page
18 18
app/views/projects/wikis/_new.html.haml
1 %div#modal-new-wiki.modal.hide 1 %div#modal-new-wiki.modal.hide
2 .modal-header 2 .modal-header
3 - %a.close{href: "#"} × 3 + %a.close{href: "#", "data-dismiss" => "modal"} ×
4 %h3.page-title New Wiki Page 4 %h3.page-title New Wiki Page
5 .modal-body 5 .modal-body
6 = label_tag :new_wiki_path do 6 = label_tag :new_wiki_path do
app/views/projects/wikis/git_access.html.haml
1 = render 'nav' 1 = render 'nav'
2 %h3.page-title 2 %h3.page-title
3 - Git Access 3 + Git access for
4 %strong= @gollum_wiki.path_with_namespace 4 %strong= @gollum_wiki.path_with_namespace
5 = render 'main_links' 5 = render 'main_links'
6 6
7 -%br  
8 .content 7 .content
9 .project_clone_panel 8 .project_clone_panel
10 .row 9 .row
app/views/public/projects/index.html.haml
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 .pull-right 7 .pull-right
8 = form_tag public_projects_path, method: :get, class: 'form-inline' do |f| 8 = form_tag public_projects_path, method: :get, class: 'form-inline' do |f|
9 .search-holder 9 .search-holder
10 - .input 10 + .controls
11 = search_field_tag :search, params[:search], placeholder: "gitlab-ci", class: "span3 search-text-input", id: "projects_search" 11 = search_field_tag :search, params[:search], placeholder: "gitlab-ci", class: "span3 search-text-input", id: "projects_search"
12 = submit_tag 'Search', class: "btn btn-primary wide" 12 = submit_tag 'Search', class: "btn btn-primary wide"
13 13
app/views/search/show.html.haml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 .search-holder 2 .search-holder
3 = label_tag :search do 3 = label_tag :search do
4 %span Looking for 4 %span Looking for
5 - .input 5 + .controls
6 = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search" 6 = search_field_tag :search, params[:search], placeholder: "issue 143", class: "input-xxlarge search-text-input", id: "dashboard_search"
7 = hidden_field_tag :project_id, params[:project_id] 7 = hidden_field_tag :project_id, params[:project_id]
8 = hidden_field_tag :group_id, params[:group_id] 8 = hidden_field_tag :group_id, params[:group_id]
app/views/shared/_filter.html.haml 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 += form_tag filter_path(entity), method: 'get' do
  2 + %fieldset
  3 + %ul.nav.nav-pills.nav-stacked
  4 + %li{class: ("active" if params[:status].blank?)}
  5 + = link_to filter_path(entity, status: nil) do
  6 + Open
  7 + %li{class: ("active" if params[:status] == 'closed')}
  8 + = link_to filter_path(entity, status: 'closed') do
  9 + Closed
  10 + %li{class: ("active" if params[:status] == 'all')}
  11 + = link_to filter_path(entity, status: 'all') do
  12 + All
  13 +
  14 + %fieldset
  15 + %legend Projects:
  16 + %ul.nav.nav-pills.nav-pills-small.nav-stacked
  17 + - @projects.each do |project|
  18 + - unless entities_per_project(project, entity).zero?
  19 + %li{class: ("active" if params[:project_id] == project.id.to_s)}
  20 + = link_to filter_path(entity, project_id: project.id) do
  21 + = project.name_with_namespace
  22 + %small.pull-right= entities_per_project(project, entity)
  23 +
  24 + %fieldset
  25 + - if params[:status].present? || params[:project_id].present?
  26 + = link_to filter_path(entity, status: nil, project_id: nil), class: 'pull-right cgray' do
  27 + %i.icon-remove
  28 + Clear filter
  29 +
app/views/shared/_issues.html.haml 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +- if @issues.any?
  2 + - @issues.group_by(&:project).each do |group|
  3 + .ui-box.small-box
  4 + - project = group[0]
  5 + .title
  6 + = link_to_project project
  7 + = link_to 'show all', project_issues_path(project), class: 'pull-right'
  8 +
  9 + %ul.well-list.issues-list
  10 + - group[1].each do |issue|
  11 + = render 'projects/issues/issue', issue: issue
  12 + = paginate @issues, theme: "gitlab"
  13 +- else
  14 + %p.nothing_here_message Nothing to show here
  15 +
app/views/shared/_merge_requests.html.haml
1 - if @merge_requests.any? 1 - if @merge_requests.any?
2 - @merge_requests.group_by(&:target_project).each do |group| 2 - @merge_requests.group_by(&:target_project).each do |group|
3 - .ui-box 3 + .ui-box.small-box
4 - project = group[0] 4 - project = group[0]
5 .title 5 .title
6 = link_to_project project 6 = link_to_project project
7 %ul.well-list.mr-list 7 %ul.well-list.mr-list
8 - group[1].each do |merge_request| 8 - group[1].each do |merge_request|
9 = render 'projects/merge_requests/merge_request', merge_request: merge_request 9 = render 'projects/merge_requests/merge_request', merge_request: merge_request
10 - %hr  
11 = paginate @merge_requests, theme: "gitlab" 10 = paginate @merge_requests, theme: "gitlab"
12 11
13 - else 12 - else
app/views/snippets/_form.html.haml
@@ -9,16 +9,16 @@ @@ -9,16 +9,16 @@
9 - @snippet.errors.full_messages.each do |msg| 9 - @snippet.errors.full_messages.each do |msg|
10 %li= msg 10 %li= msg
11 11
12 - .clearfix 12 + .control-group
13 = f.label :title 13 = f.label :title
14 - .input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true  
15 - .clearfix 14 + .controls= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
  15 + .control-group
16 = f.label "Private?" 16 = f.label "Private?"
17 - .input= f.check_box :private, {class: ''}  
18 - .clearfix 17 + .controls= f.check_box :private, {class: ''}
  18 + .control-group
19 .file-editor 19 .file-editor
20 = f.label :file_name, "File" 20 = f.label :file_name, "File"
21 - .input 21 + .controls
22 .file-holder.snippet 22 .file-holder.snippet
23 .file-title 23 .file-title
24 = f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true 24 = f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true
app/views/snippets/current_user_index.html.haml
1 %h3.page-title 1 %h3.page-title
2 My Snippets 2 My Snippets
3 - %small share code pastes with others out of git repository  
4 .pull-right 3 .pull-right
5 - = link_to new_snippet_path, class: "btn btn-small add_new grouped btn-primary", title: "New Snippet" do 4 + = link_to new_snippet_path, class: "btn btn-new grouped", title: "New Snippet" do
6 Add new snippet 5 Add new snippet
7 - = link_to snippets_path, class: "btn btn-small grouped" do 6 + = link_to snippets_path, class: "btn grouped" do
8 Discover snippets 7 Discover snippets
9 8
  9 +%p.light
  10 + Share code pastes with others out of git repository
10 %hr 11 %hr
11 12
12 .row 13 .row
app/views/snippets/index.html.haml
1 %h3.page-title 1 %h3.page-title
2 Public snippets 2 Public snippets
3 - %small share code pastes with others out of git repository  
4 3
5 .pull-right 4 .pull-right
6 - = link_to new_snippet_path, class: "btn btn-small add_new grouped btn-primary", title: "New Snippet" do 5 + = link_to new_snippet_path, class: "btn btn-new grouped", title: "New Snippet" do
7 Add new snippet 6 Add new snippet
8 - = link_to user_snippets_path(current_user), class: "btn btn-small grouped" do 7 + = link_to user_snippets_path(current_user), class: "btn grouped" do
9 My snippets 8 My snippets
10 9
  10 +%p.light
  11 + Public snippets created by you and other users are listed here
  12 +
11 %hr 13 %hr
12 = render 'snippets' 14 = render 'snippets'
13 15
app/views/snippets/show.html.haml
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 private 7 private
8 8
9 .pull-right 9 .pull-right
10 - = link_to new_snippet_path, class: "btn btn-small add_new grouped btn-primary", title: "New Snippet" do 10 + = link_to new_snippet_path, class: "btn btn-new btn-small", title: "New Snippet" do
11 Add new snippet 11 Add new snippet
12 12
13 13
app/views/users_groups/_users_group.html.haml
1 - user = member.user 1 - user = member.user
2 - return unless user 2 - return unless user
3 -%li{class: dom_class(member)} 3 +%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
4 = image_tag gravatar_icon(user.email, 16), class: "avatar s16" 4 = image_tag gravatar_icon(user.email, 16), class: "avatar s16"
5 %strong= user.name 5 %strong= user.name
6 %span.cgray= user.username 6 %span.cgray= user.username
@@ -8,12 +8,16 @@ @@ -8,12 +8,16 @@
8 %span.label.label-success It's you 8 %span.label.label-success It's you
9 9
10 %span.pull-right 10 %span.pull-right
11 - - if @group.owners.include?(user)  
12 - %span.label.label-info Group Owner  
13 - - else  
14 - = member.human_access 11 + %strong= member.human_access
15 12
16 - if show_controls && user != @group.owner && user != current_user 13 - if show_controls && user != @group.owner && user != current_user
  14 + = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
  15 + %i.icon-edit
17 = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do 16 = link_to group_users_group_path(@group, member), confirm: remove_user_from_group_message(@group, user), method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
18 %i.icon-minus.icon-white 17 %i.icon-minus.icon-white
19 18
  19 + .edit-member.hide.js-toggle-content
  20 + = form_for [@group, member], remote: true do |f|
  21 + .alert.prepend-top-20
  22 + = f.select :group_access, options_for_select(UsersGroup.group_access_roles, member.group_access)
  23 + = f.submit 'Save', class: 'btn btn-save'
app/views/users_groups/update.js.haml 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +:plain
  2 + $("##{dom_id(@member)}").replaceWith('#{escape_javascript(render(@member, member: @member, show_controls: true))}');
config/routes.rb
@@ -225,8 +225,13 @@ Gitlab::Application.routes.draw do @@ -225,8 +225,13 @@ Gitlab::Application.routes.draw do
225 end 225 end
226 end 226 end
227 227
  228 + resources :branches, only: [:index, :new, :create, :destroy] do
  229 + collection do
  230 + get :recent
  231 + end
  232 + end
  233 +
228 resources :tags, only: [:index, :new, :create, :destroy] 234 resources :tags, only: [:index, :new, :create, :destroy]
229 - resources :branches, only: [:index, :new, :create, :destroy]  
230 resources :protected_branches, only: [:index, :create, :destroy] 235 resources :protected_branches, only: [:index, :create, :destroy]
231 236
232 resources :refs, only: [] do 237 resources :refs, only: [] do
db/migrate/20130804151314_add_st_diff_to_note.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddStDiffToNote < ActiveRecord::Migration
  2 + def change
  3 + add_column :notes, :st_diff, :text, :null => true
  4 + end
  5 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20130624162710) do 14 +ActiveRecord::Schema.define(:version => 20130804151314) do
15 15
16 create_table "deploy_keys_projects", :force => true do |t| 16 create_table "deploy_keys_projects", :force => true do |t|
17 t.integer "deploy_key_id", :null => false 17 t.integer "deploy_key_id", :null => false
@@ -148,6 +148,7 @@ ActiveRecord::Schema.define(:version =&gt; 20130624162710) do @@ -148,6 +148,7 @@ ActiveRecord::Schema.define(:version =&gt; 20130624162710) do
148 t.string "line_code" 148 t.string "line_code"
149 t.string "commit_id" 149 t.string "commit_id"
150 t.integer "noteable_id" 150 t.integer "noteable_id"
  151 + t.text "st_diff"
151 end 152 end
152 153
153 add_index "notes", ["author_id"], :name => "index_notes_on_author_id" 154 add_index "notes", ["author_id"], :name => "index_notes_on_author_id"
doc/api/README.md
@@ -87,3 +87,4 @@ When listing resources you can pass the following parameters: @@ -87,3 +87,4 @@ When listing resources you can pass the following parameters:
87 87
88 + [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP 88 + [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP
89 + [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby 89 + [Ruby Wrapper](https://github.com/NARKOZ/gitlab) - Ruby
  90 ++ [python-gitlab](https://github.com/Itxaka/python-gitlab) - Python
doc/install/installation.md
@@ -71,6 +71,9 @@ Make sure you have the right version of Python installed. @@ -71,6 +71,9 @@ Make sure you have the right version of Python installed.
71 # If you get a "command not found" error create a link to the python binary 71 # If you get a "command not found" error create a link to the python binary
72 sudo ln -s /usr/bin/python /usr/bin/python2 72 sudo ln -s /usr/bin/python /usr/bin/python2
73 73
  74 + # For reStructuredText markup language support install required package:
  75 + sudo apt-get install python-docutils
  76 +
74 **Note:** In order to receive mail notifications, make sure to install a 77 **Note:** In order to receive mail notifications, make sure to install a
75 mail server. By default, Debian is shipped with exim4 whereas Ubuntu 78 mail server. By default, Debian is shipped with exim4 whereas Ubuntu
76 does not ship with one. The recommended mail server is postfix and you can install it with: 79 does not ship with one. The recommended mail server is postfix and you can install it with:
@@ -119,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia @@ -119,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia
119 cd gitlab-shell 122 cd gitlab-shell
120 123
121 # switch to right version 124 # switch to right version
122 - sudo -u git -H git checkout v1.4.0 125 + sudo -u git -H git checkout v1.7.0
123 126
124 sudo -u git -H cp config.yml.example config.yml 127 sudo -u git -H cp config.yml.example config.yml
125 128
@@ -196,6 +199,7 @@ You can change `5-3-stable` to `master` if you want the *bleeding edge* version, @@ -196,6 +199,7 @@ You can change `5-3-stable` to `master` if you want the *bleeding edge* version,
196 # Edit user.email according to what is set in gitlab.yml 199 # Edit user.email according to what is set in gitlab.yml
197 sudo -u git -H git config --global user.name "GitLab" 200 sudo -u git -H git config --global user.name "GitLab"
198 sudo -u git -H git config --global user.email "gitlab@localhost" 201 sudo -u git -H git config --global user.email "gitlab@localhost"
  202 + sudo -u git -H git config --global core.autocrlf input
199 203
200 **Important Note:** 204 **Important Note:**
201 Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup. 205 Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
doc/update/5.4-to-6.0.md
@@ -9,9 +9,13 @@ So you need to move all your global projects under group/users manually before u @@ -9,9 +9,13 @@ So you need to move all your global projects under group/users manually before u
9 9
10 #### Teams 10 #### Teams
11 11
12 -We drop teams support as separate entity for 6.0 in favor of group membership.  
13 -So now you will be able to manage group members in order to provide access to corresponding projects.  
14 - 12 +We deprecate teams as separate entity in 6.0 in favor of group membership.
  13 +The old combination of groups and teams was confusing for a lot of people.
  14 +And when the members of a team where changed this wasn't reflected in the project permissions.
  15 +In GitLab 6.0 you will be able to add members to a group with a permission level for each member.
  16 +These group members will have access to the projects in that group.
  17 +Any changes to group members will immediately be reflected in the project permissions.
  18 +You can even have multiple owners for a group, greatly simplifying administration.
15 19
16 ### 0. Backup 20 ### 0. Backup
17 21
@@ -35,7 +39,14 @@ sudo -u git -H git fetch @@ -35,7 +39,14 @@ sudo -u git -H git fetch
35 sudo -u git -H git checkout 6-0-dev 39 sudo -u git -H git checkout 6-0-dev
36 ``` 40 ```
37 41
38 -### 3. Install libs, migrations, etc. 42 +### 3. Install additional packages
  43 +
  44 +```bash
  45 +# For reStructuredText markup language support install required package:
  46 +sudo apt-get install python-docutils
  47 +```
  48 +
  49 +### 4. Install libs, migrations, etc.
39 50
40 ```bash 51 ```bash
41 cd /home/git/gitlab 52 cd /home/git/gitlab
@@ -50,15 +61,16 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production @@ -50,15 +61,16 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
50 sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production 61 sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production
51 sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production 62 sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production
52 sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production 63 sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production
  64 +sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production
53 65
54 ``` 66 ```
55 67
56 -### 4. Update config files 68 +### 5. Update config files
57 69
58 * Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example but with your settings. 70 * Make `/home/git/gitlab/config/gitlab.yml` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/gitlab.yml.example but with your settings.
59 * Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/puma.rb.example but with your settings. 71 * Make `/home/git/gitlab/config/puma.rb` same as https://github.com/gitlabhq/gitlabhq/blob/5-3-stable/config/puma.rb.example but with your settings.
60 72
61 -### 5. Update Init script 73 +### 6. Update Init script
62 74
63 ```bash 75 ```bash
64 sudo rm /etc/init.d/gitlab 76 sudo rm /etc/init.d/gitlab
@@ -66,12 +78,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5 @@ -66,12 +78,12 @@ sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlabhq/5
66 sudo chmod +x /etc/init.d/gitlab 78 sudo chmod +x /etc/init.d/gitlab
67 ``` 79 ```
68 80
69 -### 6. Start application 81 +### 7. Start application
70 82
71 sudo service gitlab start 83 sudo service gitlab start
72 sudo service nginx restart 84 sudo service nginx restart
73 85
74 -### 7. Check application status 86 +### 8. Check application status
75 87
76 Check if GitLab and its environment are configured correctly: 88 Check if GitLab and its environment are configured correctly:
77 89
@@ -81,4 +93,4 @@ To make sure you didn&#39;t miss anything run a more thorough check with: @@ -81,4 +93,4 @@ To make sure you didn&#39;t miss anything run a more thorough check with:
81 93
82 sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production 94 sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
83 95
84 -If all items are green, then congratulations upgrade complete!  
85 \ No newline at end of file 96 \ No newline at end of file
  97 +If all items are green, then congratulations upgrade complete!
features/steps/profile/profile.rb
@@ -12,7 +12,7 @@ class Profile &lt; Spinach::FeatureSteps @@ -12,7 +12,7 @@ class Profile &lt; Spinach::FeatureSteps
12 fill_in "user_skype", with: "testskype" 12 fill_in "user_skype", with: "testskype"
13 fill_in "user_linkedin", with: "testlinkedin" 13 fill_in "user_linkedin", with: "testlinkedin"
14 fill_in "user_twitter", with: "testtwitter" 14 fill_in "user_twitter", with: "testtwitter"
15 - click_button "Save" 15 + click_button "Save changes"
16 @user.reload 16 @user.reload
17 end 17 end
18 18
features/steps/profile/profile_notifications.rb
@@ -7,7 +7,7 @@ class ProfileNotifications &lt; Spinach::FeatureSteps @@ -7,7 +7,7 @@ class ProfileNotifications &lt; Spinach::FeatureSteps
7 end 7 end
8 8
9 step 'I should see global notifications settings' do 9 step 'I should see global notifications settings' do
10 - page.should have_content "Setup your notification level" 10 + page.should have_content "Notifications settings"
11 page.should have_content "Global setting" 11 page.should have_content "Global setting"
12 end 12 end
13 end 13 end
features/steps/project/project.rb
@@ -9,7 +9,7 @@ class ProjectFeature &lt; Spinach::FeatureSteps @@ -9,7 +9,7 @@ class ProjectFeature &lt; Spinach::FeatureSteps
9 end 9 end
10 10
11 And 'I save project' do 11 And 'I save project' do
12 - click_button 'Save' 12 + click_button 'Save changes'
13 end 13 end
14 14
15 Then 'I should see project with new settings' do 15 Then 'I should see project with new settings' do
features/steps/project/project_wiki.rb
@@ -5,7 +5,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps @@ -5,7 +5,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps
5 include SharedPaths 5 include SharedPaths
6 6
7 Given 'I click on the Cancel button' do 7 Given 'I click on the Cancel button' do
8 - within(:css, ".actions") do 8 + within(:css, ".form-actions") do
9 click_on "Cancel" 9 click_on "Cancel"
10 end 10 end
11 end 11 end
@@ -17,7 +17,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps @@ -17,7 +17,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps
17 17
18 Given 'I create the Wiki Home page' do 18 Given 'I create the Wiki Home page' do
19 fill_in "Content", with: '[link test](test)' 19 fill_in "Content", with: '[link test](test)'
20 - click_on "Save" 20 + click_on "Create page"
21 end 21 end
22 22
23 Then 'I should see the newly created wiki page' do 23 Then 'I should see the newly created wiki page' do
@@ -43,7 +43,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps @@ -43,7 +43,7 @@ class ProjectWiki &lt; Spinach::FeatureSteps
43 43
44 And 'I change the content' do 44 And 'I change the content' do
45 fill_in "Content", with: 'Updated Wiki Content' 45 fill_in "Content", with: 'Updated Wiki Content'
46 - click_on "Save" 46 + click_on "Save changes"
47 end 47 end
48 48
49 Then 'I should see the updated content' do 49 Then 'I should see the updated content' do
lib/api/internal.rb
1 module API 1 module API
2 # Internal access API 2 # Internal access API
3 class Internal < Grape::API 3 class Internal < Grape::API
  4 +
  5 + DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
  6 + PUSH_COMMANDS = %w{ git-receive-pack }
  7 +
4 namespace 'internal' do 8 namespace 'internal' do
5 # 9 #
6 # Check if ssh key has access to project code 10 # Check if ssh key has access to project code
@@ -26,16 +30,16 @@ module API @@ -26,16 +30,16 @@ module API
26 30
27 31
28 if key.is_a? DeployKey 32 if key.is_a? DeployKey
29 - key.projects.include?(project) && git_cmd == 'git-upload-pack' 33 + key.projects.include?(project) && DOWNLOAD_COMMANDS.include?(git_cmd)
30 else 34 else
31 user = key.user 35 user = key.user
32 36
33 return false if user.blocked? 37 return false if user.blocked?
34 38
35 action = case git_cmd 39 action = case git_cmd
36 - when 'git-upload-pack', 'git-upload-archive' 40 + when *DOWNLOAD_COMMANDS
37 then :download_code 41 then :download_code
38 - when 'git-receive-pack' 42 + when *PUSH_COMMANDS
39 then 43 then
40 if project.protected_branch?(params[:ref]) 44 if project.protected_branch?(params[:ref])
41 :push_code_to_protected_branches 45 :push_code_to_protected_branches
lib/backup/manager.rb 0 → 100644
@@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
  1 +module Backup
  2 + class Manager
  3 + def pack
  4 + # saving additional informations
  5 + s = {}
  6 + s[:db_version] = "#{ActiveRecord::Migrator.current_version}"
  7 + s[:backup_created_at] = Time.now
  8 + s[:gitlab_version] = %x{git rev-parse HEAD}.gsub(/\n/,"")
  9 + s[:tar_version] = %x{tar --version | head -1}.gsub(/\n/,"")
  10 +
  11 + Dir.chdir(Gitlab.config.backup.path)
  12 +
  13 + File.open("#{Gitlab.config.backup.path}/backup_information.yml", "w+") do |file|
  14 + file << s.to_yaml.gsub(/^---\n/,'')
  15 + end
  16 +
  17 + # create archive
  18 + print "Creating backup archive: #{s[:backup_created_at].to_i}_gitlab_backup.tar ... "
  19 + if Kernel.system("tar -cf #{s[:backup_created_at].to_i}_gitlab_backup.tar repositories/ db/ uploads/ backup_information.yml")
  20 + puts "done".green
  21 + else
  22 + puts "failed".red
  23 + end
  24 + end
  25 +
  26 + def cleanup
  27 + print "Deleting tmp directories ... "
  28 + if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml")
  29 + puts "done".green
  30 + else
  31 + puts "failed".red
  32 + end
  33 + end
  34 +
  35 + def remove_old
  36 + # delete backups
  37 + print "Deleting old backups ... "
  38 + keep_time = Gitlab.config.backup.keep_time.to_i
  39 + path = Gitlab.config.backup.path
  40 +
  41 + if keep_time > 0
  42 + removed = 0
  43 + file_list = Dir.glob(Rails.root.join(path, "*_gitlab_backup.tar"))
  44 + file_list.map! { |f| $1.to_i if f =~ /(\d+)_gitlab_backup.tar/ }
  45 + file_list.sort.each do |timestamp|
  46 + if Time.at(timestamp) < (Time.now - keep_time)
  47 + if system("rm #{timestamp}_gitlab_backup.tar")
  48 + removed += 1
  49 + end
  50 + end
  51 + end
  52 + puts "done. (#{removed} removed)".green
  53 + else
  54 + puts "skipping".yellow
  55 + end
  56 + end
  57 +
  58 + def unpack
  59 + Dir.chdir(Gitlab.config.backup.path)
  60 +
  61 + # check for existing backups in the backup dir
  62 + file_list = Dir.glob("*_gitlab_backup.tar").each.map { |f| f.split(/_/).first.to_i }
  63 + puts "no backups found" if file_list.count == 0
  64 + if file_list.count > 1 && ENV["BACKUP"].nil?
  65 + puts "Found more than one backup, please specify which one you want to restore:"
  66 + puts "rake gitlab:backup:restore BACKUP=timestamp_of_backup"
  67 + exit 1
  68 + end
  69 +
  70 + tar_file = ENV["BACKUP"].nil? ? File.join("#{file_list.first}_gitlab_backup.tar") : File.join(ENV["BACKUP"] + "_gitlab_backup.tar")
  71 +
  72 + unless File.exists?(tar_file)
  73 + puts "The specified backup doesn't exist!"
  74 + exit 1
  75 + end
  76 +
  77 + print "Unpacking backup ... "
  78 + unless Kernel.system("tar -xf #{tar_file}")
  79 + puts "failed".red
  80 + exit 1
  81 + else
  82 + puts "done".green
  83 + end
  84 +
  85 + settings = YAML.load_file("backup_information.yml")
  86 + ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0
  87 +
  88 + # backups directory is not always sub of Rails root and able to execute the git rev-parse below
  89 + begin
  90 + Dir.chdir(Rails.root)
  91 +
  92 + # restoring mismatching backups can lead to unexpected problems
  93 + if settings[:gitlab_version] != %x{git rev-parse HEAD}.gsub(/\n/, "")
  94 + puts "GitLab version mismatch:".red
  95 + puts " Your current HEAD differs from the HEAD in the backup!".red
  96 + puts " Please switch to the following revision and try again:".red
  97 + puts " revision: #{settings[:gitlab_version]}".red
  98 + exit 1
  99 + end
  100 + ensure
  101 + # chdir back to original intended dir
  102 + Dir.chdir(Gitlab.config.backup.path)
  103 + end
  104 + end
  105 + end
  106 +end
lib/extracts_path.rb
@@ -95,13 +95,9 @@ module ExtractsPath @@ -95,13 +95,9 @@ module ExtractsPath
95 # resolved (e.g., when a user inserts an invalid path or ref). 95 # resolved (e.g., when a user inserts an invalid path or ref).
96 def assign_ref_vars 96 def assign_ref_vars
97 @id = get_id 97 @id = get_id
98 -  
99 @ref, @path = extract_ref(@id) 98 @ref, @path = extract_ref(@id)
100 -  
101 @repo = @project.repository 99 @repo = @project.repository
102 -  
103 @commit = @repo.commit(@ref) 100 @commit = @repo.commit(@ref)
104 -  
105 @tree = Tree.new(@repo, @commit.id, @ref, @path) 101 @tree = Tree.new(@repo, @commit.id, @ref, @path)
106 @hex_path = Digest::SHA1.hexdigest(@path) 102 @hex_path = Digest::SHA1.hexdigest(@path)
107 @logs_path = logs_file_project_ref_path(@project, @ref, @path) 103 @logs_path = logs_file_project_ref_path(@project, @ref, @path)
lib/gitlab/blacklist.rb
@@ -3,7 +3,7 @@ module Gitlab @@ -3,7 +3,7 @@ module Gitlab
3 extend self 3 extend self
4 4
5 def path 5 def path
6 - %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services) 6 + %w(admin dashboard groups help profile projects search public assets u s teams merge_requests issues users snippets services repository)
7 end 7 end
8 end 8 end
9 end 9 end
lib/gitlab/diff_parser.rb 0 → 100644
@@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
  1 +module Gitlab
  2 + class DiffParser
  3 + include Enumerable
  4 +
  5 + attr_reader :lines, :new_path
  6 +
  7 + def initialize(diff)
  8 + @lines = diff.diff.lines.to_a
  9 + @new_path = diff.new_path
  10 + end
  11 +
  12 + def each
  13 + line_old = 1
  14 + line_new = 1
  15 + type = nil
  16 +
  17 + lines_arr = ::Gitlab::InlineDiff.processing lines
  18 + lines_arr.each do |line|
  19 + raw_line = line.dup
  20 +
  21 + next if line.match(/^\-\-\- \/dev\/null/)
  22 + next if line.match(/^\+\+\+ \/dev\/null/)
  23 + next if line.match(/^\-\-\- a/)
  24 + next if line.match(/^\+\+\+ b/)
  25 +
  26 + full_line = html_escape(line.gsub(/\n/, ''))
  27 + full_line = ::Gitlab::InlineDiff.replace_markers full_line
  28 +
  29 + if line.match(/^@@ -/)
  30 + type = "match"
  31 +
  32 + line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
  33 + line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
  34 +
  35 + next if line_old == 1 && line_new == 1 #top of file
  36 + yield(full_line, type, nil, nil, nil)
  37 + next
  38 + else
  39 + type = identification_type(line)
  40 + line_code = generate_line_code(new_path, line_new, line_old)
  41 + yield(full_line, type, line_code, line_new, line_old, raw_line)
  42 + end
  43 +
  44 +
  45 + if line[0] == "+"
  46 + line_new += 1
  47 + elsif line[0] == "-"
  48 + line_old += 1
  49 + else
  50 + line_new += 1
  51 + line_old += 1
  52 + end
  53 + end
  54 + end
  55 +
  56 + private
  57 +
  58 + def identification_type(line)
  59 + if line[0] == "+"
  60 + "new"
  61 + elsif line[0] == "-"
  62 + "old"
  63 + else
  64 + nil
  65 + end
  66 + end
  67 +
  68 + def generate_line_code(path, line_new, line_old)
  69 + "#{Digest::SHA1.hexdigest(path)}_#{line_old}_#{line_new}"
  70 + end
  71 +
  72 + def html_escape str
  73 + replacements = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
  74 + str.gsub(/[&"'><]/, replacements)
  75 + end
  76 + end
  77 +end
lib/gitlab/markdown.rb
@@ -167,7 +167,7 @@ module Gitlab @@ -167,7 +167,7 @@ module Gitlab
167 167
168 def reference_user(identifier) 168 def reference_user(identifier)
169 if member = @project.team_members.find { |user| user.username == identifier } 169 if member = @project.team_members.find { |user| user.username == identifier }
170 - link_to("@#{identifier}", user_path(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) if member 170 + link_to("@#{identifier}", user_url(identifier), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) if member
171 end 171 end
172 end 172 end
173 173
lib/gitlab/satellite/edit_file_action.rb
@@ -49,7 +49,7 @@ module Gitlab @@ -49,7 +49,7 @@ module Gitlab
49 protected 49 protected
50 50
51 def can_edit?(last_commit) 51 def can_edit?(last_commit)
52 - current_last_commit = @project.repository.last_commit_for(ref, file_path).sha 52 + current_last_commit = Gitlab::Git::Commit.last_for_path(@project.repository, ref, file_path).sha
53 last_commit == current_last_commit 53 last_commit == current_last_commit
54 end 54 end
55 end 55 end
lib/tasks/gitlab/backup.rake
@@ -11,49 +11,10 @@ namespace :gitlab do @@ -11,49 +11,10 @@ namespace :gitlab do
11 Rake::Task["gitlab:backup:repo:create"].invoke 11 Rake::Task["gitlab:backup:repo:create"].invoke
12 Rake::Task["gitlab:backup:uploads:create"].invoke 12 Rake::Task["gitlab:backup:uploads:create"].invoke
13 13
14 -  
15 - # saving additional informations  
16 - s = {}  
17 - s[:db_version] = "#{ActiveRecord::Migrator.current_version}"  
18 - s[:backup_created_at] = Time.now  
19 - s[:gitlab_version] = %x{git rev-parse HEAD}.gsub(/\n/,"")  
20 - s[:tar_version] = %x{tar --version | head -1}.gsub(/\n/,"")  
21 -  
22 - Dir.chdir(Gitlab.config.backup.path)  
23 -  
24 - File.open("#{Gitlab.config.backup.path}/backup_information.yml", "w+") do |file|  
25 - file << s.to_yaml.gsub(/^---\n/,'')  
26 - end  
27 -  
28 - # create archive  
29 - print "Creating backup archive: #{s[:backup_created_at].to_i}_gitlab_backup.tar ... "  
30 - if Kernel.system("tar -cf #{s[:backup_created_at].to_i}_gitlab_backup.tar repositories/ db/ uploads/ backup_information.yml")  
31 - puts "done".green  
32 - else  
33 - puts "failed".red  
34 - end  
35 -  
36 - # cleanup: remove tmp files  
37 - print "Deleting tmp directories ... "  
38 - if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml")  
39 - puts "done".green  
40 - else  
41 - puts "failed".red  
42 - end  
43 -  
44 - # delete backups  
45 - print "Deleting old backups ... "  
46 - if Gitlab.config.backup.keep_time > 0  
47 - file_list = Dir.glob("*_gitlab_backup.tar").map { |f| f.split(/_/).first.to_i }  
48 - file_list.sort.each do |timestamp|  
49 - if Time.at(timestamp) < (Time.now - Gitlab.config.backup.keep_time)  
50 - %x{rm #{timestamp}_gitlab_backup.tar}  
51 - end  
52 - end  
53 - puts "done".green  
54 - else  
55 - puts "skipping".yellow  
56 - end 14 + backup = Backup::Manager.new
  15 + backup.pack
  16 + backup.cleanup
  17 + backup.remove_old
57 end 18 end
58 19
59 # Restore backup of GitLab system 20 # Restore backup of GitLab system
@@ -61,64 +22,15 @@ namespace :gitlab do @@ -61,64 +22,15 @@ namespace :gitlab do
61 task restore: :environment do 22 task restore: :environment do
62 warn_user_is_not_gitlab 23 warn_user_is_not_gitlab
63 24
64 - Dir.chdir(Gitlab.config.backup.path)  
65 -  
66 - # check for existing backups in the backup dir  
67 - file_list = Dir.glob("*_gitlab_backup.tar").each.map { |f| f.split(/_/).first.to_i }  
68 - puts "no backups found" if file_list.count == 0  
69 - if file_list.count > 1 && ENV["BACKUP"].nil?  
70 - puts "Found more than one backup, please specify which one you want to restore:"  
71 - puts "rake gitlab:backup:restore BACKUP=timestamp_of_backup"  
72 - exit 1  
73 - end  
74 -  
75 - tar_file = ENV["BACKUP"].nil? ? File.join("#{file_list.first}_gitlab_backup.tar") : File.join(ENV["BACKUP"] + "_gitlab_backup.tar")  
76 -  
77 - unless File.exists?(tar_file)  
78 - puts "The specified backup doesn't exist!"  
79 - exit 1  
80 - end  
81 -  
82 - print "Unpacking backup ... "  
83 - unless Kernel.system("tar -xf #{tar_file}")  
84 - puts "failed".red  
85 - exit 1  
86 - else  
87 - puts "done".green  
88 - end  
89 -  
90 - settings = YAML.load_file("backup_information.yml")  
91 - ENV["VERSION"] = "#{settings[:db_version]}" if settings[:db_version].to_i > 0  
92 -  
93 - # backups directory is not always sub of Rails root and able to execute the git rev-parse below  
94 - begin  
95 - Dir.chdir(Rails.root)  
96 -  
97 - # restoring mismatching backups can lead to unexpected problems  
98 - if settings[:gitlab_version] != %x{git rev-parse HEAD}.gsub(/\n/, "")  
99 - puts "GitLab version mismatch:".red  
100 - puts " Your current HEAD differs from the HEAD in the backup!".red  
101 - puts " Please switch to the following revision and try again:".red  
102 - puts " revision: #{settings[:gitlab_version]}".red  
103 - exit 1  
104 - end  
105 - ensure  
106 - # chdir back to original intended dir  
107 - Dir.chdir(Gitlab.config.backup.path)  
108 - end 25 + backup = Backup::Manager.new
  26 + backup.unpack
109 27
110 Rake::Task["gitlab:backup:db:restore"].invoke 28 Rake::Task["gitlab:backup:db:restore"].invoke
111 Rake::Task["gitlab:backup:repo:restore"].invoke 29 Rake::Task["gitlab:backup:repo:restore"].invoke
112 Rake::Task["gitlab:backup:uploads:restore"].invoke 30 Rake::Task["gitlab:backup:uploads:restore"].invoke
113 Rake::Task["gitlab:shell:setup"].invoke 31 Rake::Task["gitlab:shell:setup"].invoke
114 32
115 - # cleanup: remove tmp files  
116 - print "Deleting tmp directories ... "  
117 - if Kernel.system("rm -rf repositories/ db/ uploads/ backup_information.yml")  
118 - puts "done".green  
119 - else  
120 - puts "failed".red  
121 - end 33 + backup.cleanup
122 end 34 end
123 35
124 namespace :repo do 36 namespace :repo do
lib/tasks/migrate/migrate_inline_notes.rake 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +desc "GITLAB | Migrate inline notes"
  2 +task migrate_inline_notes: :environment do
  3 + Note.where('line_code IS NOT NULL').find_each(batch_size: 100) do |note|
  4 + begin
  5 + note.set_diff
  6 + if note.save
  7 + print '.'
  8 + else
  9 + print 'F'
  10 + end
  11 + rescue
  12 + print 'F'
  13 + end
  14 + end
  15 +end
  16 +
lib/tasks/migrate/migrate_keys.rake
1 desc "GITLAB | Migrate SSH Keys" 1 desc "GITLAB | Migrate SSH Keys"
2 task migrate_keys: :environment do 2 task migrate_keys: :environment do
3 puts "This will add fingerprint to ssh keys in db" 3 puts "This will add fingerprint to ssh keys in db"
  4 + puts "If you have duplicate keys https://github.com/gitlabhq/gitlabhq/issues/4453 all but the first will be deleted".yellow
4 ask_to_continue 5 ask_to_continue
5 6
6 Key.find_each(batch_size: 20) do |key| 7 Key.find_each(batch_size: 20) do |key|
7 if key.valid? && key.save 8 if key.valid? && key.save
8 print '.' 9 print '.'
  10 + elsif key.fingerprint.present?
  11 + puts "\nDeleting #{key.inspect}".yellow
  12 + key.destroy
9 else 13 else
10 print 'F' 14 print 'F'
11 end 15 end
12 end 16 end
  17 + print "\n"
13 end 18 end
14 19
15 20
spec/controllers/commit_controller_spec.rb
@@ -2,8 +2,8 @@ require &#39;spec_helper&#39; @@ -2,8 +2,8 @@ require &#39;spec_helper&#39;
2 2
3 describe Projects::CommitController do 3 describe Projects::CommitController do
4 let(:project) { create(:project_with_code) } 4 let(:project) { create(:project_with_code) }
5 - let(:user) { create(:user) }  
6 - let(:commit) { project.repository.last_commit_for("master") } 5 + let(:user) { create(:user) }
  6 + let(:commit) { project.repository.commit("master") }
7 7
8 before do 8 before do
9 sign_in(user) 9 sign_in(user)
spec/features/security/project_access_spec.rb
@@ -175,8 +175,8 @@ describe &quot;Application access&quot; do @@ -175,8 +175,8 @@ describe &quot;Application access&quot; do
175 it { should be_denied_for :visitor } 175 it { should be_denied_for :visitor }
176 end 176 end
177 177
178 - describe "GET /project_code/repository" do  
179 - subject { project_repository_path(project) } 178 + describe "GET /project_code/branches/recent" do
  179 + subject { recent_project_branches_path(project) }
180 180
181 it { should be_allowed_for master } 181 it { should be_allowed_for master }
182 it { should be_allowed_for reporter } 182 it { should be_allowed_for reporter }
@@ -186,7 +186,7 @@ describe &quot;Application access&quot; do @@ -186,7 +186,7 @@ describe &quot;Application access&quot; do
186 it { should be_denied_for :visitor } 186 it { should be_denied_for :visitor }
187 end 187 end
188 188
189 - describe "GET /project_code/repository/branches" do 189 + describe "GET /project_code/branches" do
190 subject { project_branches_path(project) } 190 subject { project_branches_path(project) }
191 191
192 before do 192 before do
@@ -202,7 +202,7 @@ describe &quot;Application access&quot; do @@ -202,7 +202,7 @@ describe &quot;Application access&quot; do
202 it { should be_denied_for :visitor } 202 it { should be_denied_for :visitor }
203 end 203 end
204 204
205 - describe "GET /project_code/repository/tags" do 205 + describe "GET /project_code/tags" do
206 subject { project_tags_path(project) } 206 subject { project_tags_path(project) }
207 207
208 before do 208 before do
@@ -417,8 +417,8 @@ describe &quot;Application access&quot; do @@ -417,8 +417,8 @@ describe &quot;Application access&quot; do
417 it { should be_denied_for :visitor } 417 it { should be_denied_for :visitor }
418 end 418 end
419 419
420 - describe "GET /project_code/repository" do  
421 - subject { project_repository_path(project) } 420 + describe "GET /project_code/branches/recent" do
  421 + subject { recent_project_branches_path(project) }
422 422
423 it { should be_allowed_for master } 423 it { should be_allowed_for master }
424 it { should be_allowed_for reporter } 424 it { should be_allowed_for reporter }
@@ -428,7 +428,7 @@ describe &quot;Application access&quot; do @@ -428,7 +428,7 @@ describe &quot;Application access&quot; do
428 it { should be_denied_for :visitor } 428 it { should be_denied_for :visitor }
429 end 429 end
430 430
431 - describe "GET /project_code/repository/branches" do 431 + describe "GET /project_code/branches" do
432 subject { project_branches_path(project) } 432 subject { project_branches_path(project) }
433 433
434 before do 434 before do
@@ -444,7 +444,7 @@ describe &quot;Application access&quot; do @@ -444,7 +444,7 @@ describe &quot;Application access&quot; do
444 it { should be_denied_for :visitor } 444 it { should be_denied_for :visitor }
445 end 445 end
446 446
447 - describe "GET /project_code/repository/tags" do 447 + describe "GET /project_code/tags" do
448 subject { project_tags_path(project) } 448 subject { project_tags_path(project) }
449 449
450 before do 450 before do
spec/requests/api/internal_spec.rb
@@ -100,6 +100,32 @@ describe API::API do @@ -100,6 +100,32 @@ describe API::API do
100 end 100 end
101 end 101 end
102 end 102 end
  103 +
  104 + context "deploy key" do
  105 + let(:key) { create(:deploy_key) }
  106 +
  107 + context "added to project" do
  108 + before do
  109 + key.projects << project
  110 + end
  111 +
  112 + it do
  113 + archive(key, project)
  114 +
  115 + response.status.should == 200
  116 + response.body.should == 'true'
  117 + end
  118 + end
  119 +
  120 + context "not added to project" do
  121 + it do
  122 + archive(key, project)
  123 +
  124 + response.status.should == 200
  125 + response.body.should == 'false'
  126 + end
  127 + end
  128 + end
103 end 129 end
104 130
105 def pull(key, project) 131 def pull(key, project)
@@ -121,4 +147,14 @@ describe API::API do @@ -121,4 +147,14 @@ describe API::API do
121 action: 'git-receive-pack' 147 action: 'git-receive-pack'
122 ) 148 )
123 end 149 end
  150 +
  151 + def archive(key, project)
  152 + get(
  153 + api("/internal/allowed"),
  154 + ref: 'master',
  155 + key_id: key.id,
  156 + project: project.path_with_namespace,
  157 + action: 'git-upload-archive'
  158 + )
  159 + end
124 end 160 end
spec/services/notification_service_spec.rb
@@ -47,7 +47,7 @@ describe NotificationService do @@ -47,7 +47,7 @@ describe NotificationService do
47 end 47 end
48 48
49 context 'commit note' do 49 context 'commit note' do
50 - let(:note) { create :note_on_commit } 50 + let(:note) { create(:note_on_commit) }
51 51
52 before do 52 before do
53 build_team(note.project) 53 build_team(note.project)
@@ -55,32 +55,35 @@ describe NotificationService do @@ -55,32 +55,35 @@ describe NotificationService do
55 55
56 describe :new_note do 56 describe :new_note do
57 it do 57 it do
58 - should_email(@u_watcher.id)  
59 - should_not_email(note.author_id)  
60 - should_not_email(@u_participating.id)  
61 - should_not_email(@u_disabled.id) 58 + should_email(@u_watcher.id, note)
  59 + should_not_email(@u_mentioned.id, note)
  60 + should_not_email(note.author_id, note)
  61 + should_not_email(@u_participating.id, note)
  62 + should_not_email(@u_disabled.id, note)
62 notification.new_note(note) 63 notification.new_note(note)
63 end 64 end
64 65
65 it do 66 it do
66 - create(:note_on_commit, 67 + new_note = create(:note_on_commit,
67 author: @u_participating, 68 author: @u_participating,
68 project_id: note.project_id, 69 project_id: note.project_id,
69 - commit_id: note.commit_id)  
70 -  
71 - should_email(@u_watcher.id)  
72 - should_email(@u_participating.id)  
73 - should_not_email(note.author_id)  
74 - should_not_email(@u_disabled.id)  
75 - notification.new_note(note) 70 + commit_id: note.commit_id,
  71 + note: '@mention referenced')
  72 +
  73 + should_email(@u_watcher.id, new_note)
  74 + should_email(@u_mentioned.id, new_note)
  75 + should_not_email(new_note.author_id, new_note)
  76 + should_not_email(@u_participating.id, new_note)
  77 + should_not_email(@u_disabled.id, new_note)
  78 + notification.new_note(new_note)
76 end 79 end
77 80
78 - def should_email(user_id)  
79 - Notify.should_receive(:note_commit_email).with(user_id, note.id) 81 + def should_email(user_id, n)
  82 + Notify.should_receive(:note_commit_email).with(user_id, n.id)
80 end 83 end
81 84
82 - def should_not_email(user_id)  
83 - Notify.should_not_receive(:note_commit_email).with(user_id, note.id) 85 + def should_not_email(user_id, n)
  86 + Notify.should_not_receive(:note_commit_email).with(user_id, n.id)
84 end 87 end
85 end 88 end
86 end 89 end