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

Too many changes.

To preserve performance only 100 of 165 files displayed.

.gitignore
... ... @@ -30,3 +30,5 @@ vendor/bundle/*
30 30 rails_best_practices_output.html
31 31 doc/code/*
32 32 .secret
  33 +*.log
  34 +public/uploads.*
... ...
CONTRIBUTING.md
... ... @@ -2,6 +2,12 @@
2 2  
3 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 11 ## Closing policy for issues and pull requests
6 12  
7 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.
... ...
Gemfile
... ... @@ -23,7 +23,7 @@ gem 'omniauth-github'
23 23  
24 24 # Extracting information from a git repository
25 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 28 # Ruby/Rack Git Smart-HTTP Server Handler
29 29 gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
... ...
Gemfile.lock
... ... @@ -176,7 +176,7 @@ GEM
176 176 gitlab-pygments.rb (0.3.2)
177 177 posix-spawn (~> 0.3.6)
178 178 yajl-ruby (~> 1.1.0)
179   - gitlab_git (1.4.1)
  179 + gitlab_git (2.0.0.pre)
180 180 activesupport (~> 3.2.13)
181 181 github-linguist (~> 2.3.4)
182 182 gitlab-grit (~> 2.6.0)
... ... @@ -275,7 +275,7 @@ GEM
275 275 minitest (4.7.4)
276 276 modernizr (2.6.2)
277 277 sprockets (~> 2.0)
278   - multi_json (1.7.7)
  278 + multi_json (1.7.8)
279 279 multi_xml (0.5.4)
280 280 multipart-post (1.2.0)
281 281 mysql2 (0.3.11)
... ... @@ -568,7 +568,7 @@ DEPENDENCIES
568 568 gitlab-gollum-lib (~> 1.0.1)
569 569 gitlab-grack (~> 1.0.1)
570 570 gitlab-pygments.rb (~> 0.3.2)
571   - gitlab_git (~> 1.4.1)
  571 + gitlab_git (~> 2.0.0.pre)
572 572 gitlab_meta (= 6.0)
573 573 gitlab_omniauth-ldap (= 1.0.3)
574 574 gon
... ...
PROCESS.md 0 → 100644
... ... @@ -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 +
... ...
README.md
... ... @@ -147,6 +147,8 @@ or start each component separately
147 147  
148 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 152 * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
151 153  
152 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 11 container = $(".js-toggle-visibility-container")
12 12 container.toggleClass("hide")
13 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 62 cuday = 0
63 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 68 for day, mm in @days
69 69 if cuday isnt day[0]
70 70 # Dates
71   - r.text(36, @offsetY + @unitTime * mm, day[0])
  71 + r.text(55, @offsetY + @unitTime * mm, day[0])
72 72 .attr(
73 73 font: "12px Monaco, monospace"
74   - fill: "#DDD"
  74 + fill: "#BBB"
75 75 )
76 76 cuday = day[0]
77 77  
78 78 if cumonth isnt day[1]
79 79 # Months
80   - r.text(13, @offsetY + @unitTime * mm, day[1])
  80 + r.text(20, @offsetY + @unitTime * mm, day[1])
81 81 .attr(
82 82 font: "12px Monaco, monospace"
83 83 fill: "#EEE"
... ...
app/assets/javascripts/dispatcher.js.coffee
... ... @@ -39,7 +39,9 @@ class Dispatcher
39 39  
40 40 switch path.first()
41 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 46 initSearch: ->
45 47 autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts')
... ...
app/assets/javascripts/extensions/jquery.js.coffee
... ... @@ -7,3 +7,7 @@ $.fn.enableButton = ->
7 7 $(@).removeAttr('disabled').
8 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 44 tpl: @Issues.template
45 45 callbacks:
46 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 49 input.one "focus", =>
50 50 $.getJSON(@dataSource).done (data) ->
... ...
app/assets/javascripts/main.js.coffee
... ... @@ -119,7 +119,7 @@ $ ->
119 119  
120 120  
121 121 # Commit show suppressed diff
122   - $(".supp_diff_link").bind "click", ->
  122 + $(".content").on "click", ".supp_diff_link", ->
123 123 $(@).next('table').show()
124 124 $(@).remove()
125 125  
... ...
app/assets/javascripts/merge_requests.js.coffee
... ... @@ -22,12 +22,7 @@ class MergeRequest
22 22 this.$('.show-all-commits').on 'click', =>
23 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 27 # Local jQuery finder
33 28 $: (selector) ->
... ...
app/assets/javascripts/notes.js
... ... @@ -227,10 +227,11 @@ var NoteList = {
227 227 // Show the attachment delete link
228 228 note.find(".js-note-attachment-delete").show();
229 229  
  230 + GitLab.GfmAutoComplete.setup();
  231 +
230 232 var form = note.find(".note-edit-form");
231 233 form.show();
232 234  
233   -
234 235 var textarea = form.find("textarea");
235 236 var p = $("<p></p>").text(textarea.val());
236 237 var hidden_div = $('<div class="note-original-content"></div>').append(p);
... ...
app/assets/javascripts/wikis.js.coffee
1 1 class Wikis
2 2 constructor: ->
3   - modal = $('#modal-new-wiki').modal({modal: true, show:false})
4   -
5   - $('.add-new-wiki').bind "click", ->
6   - modal.show()
7   -
8 3 $('.build-new-wiki').bind "click", ->
9 4 field = $('#new_wiki_path')
10 5 slug = field.val()
... ... @@ -13,7 +8,5 @@ class Wikis
13 8 if(slug.length > 0)
14 9 location.href = path + "/" + slug
15 10  
16   - $('.modal-header .close').bind "click", ->
17   - modal.hide()
18 11  
19 12 @Wikis = Wikis
... ...
app/assets/stylesheets/common.scss
... ... @@ -81,33 +81,6 @@ span.update-author {
81 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 84 .field_with_errors {
112 85 display: inline;
113 86 }
... ... @@ -121,15 +94,6 @@ ul.breadcrumb {
121 94 }
122 95  
123 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 97 font-size: 16px;
134 98 }
135 99 }
... ...
app/assets/stylesheets/gitlab_bootstrap.scss
... ... @@ -2,11 +2,49 @@
2 2 $baseFontSize: 13px !default;
3 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 41 @import "bootstrap/responsive-utilities";
8 42 @import "bootstrap/responsive-1200px-min";
9 43  
  44 +/**
  45 + * Font icons
  46 + *
  47 + */
10 48 @import "font-awesome";
11 49  
12 50 /**
... ... @@ -26,3 +64,4 @@ $baseLineHeight: 18px !default;
26 64 @import "gitlab_bootstrap/files.scss";
27 65 @import "gitlab_bootstrap/tables.scss";
28 66 @import "gitlab_bootstrap/lists.scss";
  67 +@import "gitlab_bootstrap/forms.scss";
... ...
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
... ... @@ -10,15 +10,34 @@
10 10 *
11 11 */
12 12 .ui-box {
13   - background: #F9F9F9;
  13 + background: #FFF;
14 14 margin-bottom: 20px;
15 15 border: 1px solid #CCC;
16 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 34 &.ui-box-show {
20 35 margin:20px 0;
21 36 background: #FFF;
  37 +
  38 + .control-group {
  39 + margin-bottom: 0;
  40 + }
22 41 }
23 42  
24 43 &.ui-box-danger {
... ... @@ -71,10 +90,6 @@
71 90 border-top: 1px solid #eee;
72 91 }
73 92  
74   - &.white {
75   - background: #fff;
76   - }
77   -
78 93 ul {
79 94 margin: 0;
80 95 }
... ... @@ -102,6 +117,8 @@
102 117  
103 118 .btn {
104 119 vertical-align: middle;
  120 + padding: 4px 12px;
  121 + @include box-shadow(0 0px 1px 1px #f2f2f2);
105 122 }
106 123  
107 124 .nav-pills {
... ...
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 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 14 @include linear-gradient(#f1f1f1, #e1e1e1);
3 15 text-shadow: 0 1px 1px #FFF;
4   - border-color: #BBB;
  16 + text-decoration: none;
5 17  
  18 + &.hover,
6 19 &:hover {
  20 + color: $style_color;
7 21 background: #f1f1f1;
8   - @include linear-gradient(#fAfAfA, #f1f1f1);
9 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 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 101 &.btn-create {
58 102 @extend .wide;
59 103 @extend .btn-success;
... ... @@ -67,12 +111,6 @@
67 111 &.btn-close,
68 112 &.btn-remove {
69 113 @extend .btn-danger;
70   - border-color: #BD362F;
71   -
72   - &:hover {
73   - color: #fff;
74   - background: #EE4E49;
75   - }
76 114 }
77 115  
78 116 &.btn-cancel {
... ... @@ -84,13 +122,9 @@
84 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 130 &.btn-tiny {
... ... @@ -104,9 +138,4 @@
104 138 margin-right: 7px;
105 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 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 59 /** FORMS **/
54 60 input[type='search'].search-text-input {
... ... @@ -66,7 +72,7 @@ input[type=&#39;text&#39;].danger {
66 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 77 .tab-content {
72 78 overflow: visible;
... ... @@ -90,3 +96,11 @@ pre.well-pre {
90 96 border-radius: 0;
91 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 3 *
4 4 */
5 5 .file-holder {
6   - border: 1px solid #BBB;
  6 + border: 1px solid #CCC;
7 7 margin-bottom: 1em;
8   - @include solid-shade;
9 8  
10 9 .file-title {
11 10 border-bottom: 1px solid #bbb;
12 11 @include bg-dark-gray-gradient;
  12 + text-shadow: 0 1px 1px #fff;
13 13 margin: 0;
14 14 font-weight: normal;
15 15 font-weight: bold;
16 16 text-align: left;
17   - color: #666;
  17 + color: $style_color;
18 18 padding: 9px 10px;
19 19 height: 18px;
20 20  
... ...
app/assets/stylesheets/gitlab_bootstrap/forms.scss 0 → 100644
... ... @@ -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 6 margin: 0;
7 7 list-style: none;
8 8 li {
9   - background-color: #FFF;
10 9 padding: 10px;
11 10 min-height: 20px;
12 11 border-bottom: 1px solid #eee;
... ... @@ -84,4 +83,13 @@ ul.bordered-list {
84 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 90 @mixin page-title {
91 91 color: $style_color;
92 92 font-size: 20px;
93   - font-weight: normal;
94 93 line-height: 1.5;
95 94 margin-top: 0px;
96 95 margin-bottom: 15px;
... ...
app/assets/stylesheets/gitlab_bootstrap/nav.scss
... ... @@ -10,6 +10,7 @@
10 10 > li > a {
11 11 @include border-radius(0);
12 12 }
  13 +
13 14 &.nav-stacked {
14 15 > li > a {
15 16 border-left: 4px solid #EEE;
... ... @@ -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 42 .nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
... ...
app/assets/stylesheets/gitlab_bootstrap/tables.scss
1 1 table {
2 2 @extend .table;
3 3 @extend .table-striped;
4   - @include solid-shade;
5   - border: 1px solid #bbb;
  4 + border: 1px solid #CCC;
6 5 width: 100%;
7 6  
8 7 &.low {
... ... @@ -20,7 +19,7 @@ table {
20 19 th {
21 20 font-weight: bold;
22 21 vertical-align: middle;
23   - border-bottom: 1px solid #bbb;
  22 + border-bottom: 1px solid #CCC;
24 23 text-shadow: 0 1px 1px #fff;
25 24 @include bg-dark-gray-gradient;
26 25  
... ... @@ -46,11 +45,11 @@ table {
46 45 }
47 46  
48 47 &:first-child {
49   - border-left: 1px solid #bbb;
  48 + border-left: 1px solid #CCC;
50 49 }
51 50  
52 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 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 10 h1.page-title {
7 11 @include page-title;
... ... @@ -48,13 +52,6 @@ a {
48 52 text-decoration: underline;
49 53 }
50 54  
51   - &.btn {
52   - color: $style_color;
53   - &:hover {
54   - color: $style_color;
55   - }
56   - }
57   -
58 55 &.dark {
59 56 color: $style_color;
60 57 }
... ...
app/assets/stylesheets/sections/commits.scss
... ... @@ -421,8 +421,8 @@
421 421  
422 422 .commits-compare-switch{
423 423 background: url("switch_icon.png") no-repeat center center;
424   - width: 16px;
425   - height: 18px;
  424 + width: 22px;
  425 + height: 22px;
426 426 text-indent: -9999px;
427 427 float: left;
428 428 margin-right: 9px;
... ... @@ -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 44 margin: 0;
45 45 margin-right: 10px;
46 46 position: relative;
47   - top: 8px;
  47 + top: 10px;
48 48 height: 22px;
49 49 }
50 50  
... ... @@ -52,6 +52,10 @@ input.check_all_issues {
52 52 .title {
53 53 height: 40px;
54 54 }
  55 +
  56 + form {
  57 + margin: 0;
  58 + }
55 59 }
56 60  
57 61 .btn.close_issue {
... ... @@ -88,14 +92,11 @@ input.check_all_issues {
88 92 }
89 93  
90 94 .update_selected_issues {
91   - position: relative;
92   - top:5px;
93 95 margin-left: 4px;
94   - float: left;
95 96 }
96 97  
97 98 .update_issues_text {
98   - padding: 3px;
  99 + padding: 5px;
99 100 line-height: 28px;
100 101 float: left;
101 102 color: #479;
... ...
app/assets/stylesheets/sections/nav.scss
... ... @@ -7,7 +7,7 @@
7 7  
8 8 ul {
9 9 margin: auto;
10   - height: 42px;
  10 + height: 40px;
11 11 overflow: hidden;
12 12 .count {
13 13 font-weight: normal;
... ... @@ -74,7 +74,7 @@
74 74 text-align: center;
75 75 font-weight: normal;
76 76 height: 38px;
77   - line-height: 36px;
  77 + line-height: 34px;
78 78 color: #777;
79 79 text-shadow: 0 1px 1px white;
80 80 padding: 0 10px;
... ...
app/assets/stylesheets/sections/projects.scss
1 1 .new_project,
2 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 3 fieldset.features {
21 4 .control-label {
22 5 font-weight: bold;
... ... @@ -30,6 +13,10 @@
30 13 padding: 4px 7px;
31 14 border: 1px solid #CCC;
32 15 margin-bottom: 20px;
  16 +
  17 + .btn {
  18 + padding: 4px 12px;
  19 + }
33 20 }
34 21  
35 22 .project_clone_holder {
... ... @@ -114,7 +101,7 @@ ul.nav.nav-projects-tabs {
114 101 .public-clone {
115 102 background: #333;
116 103 color: #f5f5f5;
117   - padding: 5px 10px;
  104 + padding: 6px 10px;
118 105 margin: 1px;
119 106 font-weight: normal;
120 107 }
... ...
app/assets/stylesheets/sections/tree.scss
... ... @@ -104,6 +104,8 @@
104 104 }
105 105  
106 106 .tree-btn-group {
  107 + top: 2px;
  108 +
107 109 .btn {
108 110 margin-right: 0px;
109 111 padding: 2px 10px;
... ...
app/assets/stylesheets/themes/ui_mars.scss
... ... @@ -31,8 +31,4 @@
31 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 11 end
12 12  
13 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 16 end
17 17  
18 18 if params[:search].present?
... ...
app/contexts/merge_requests_load_context.rb
... ... @@ -2,7 +2,7 @@
2 2 # based on filtering passed via params for @project
3 3 class MergeRequestsLoadContext < BaseContext
4 4 def execute
5   - type = params[:f]
  5 + type = params[:status]
6 6  
7 7 merge_requests = project.merge_requests
8 8  
... ...
app/contexts/search_context.rb
... ... @@ -11,7 +11,7 @@ class SearchContext
11 11 return result unless query.present?
12 12  
13 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 16 # Search inside singe project
17 17 project = projects.first if projects.length == 1
... ... @@ -19,8 +19,8 @@ class SearchContext
19 19 if params[:search_code].present?
20 20 result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo?
21 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 24 result[:wiki_pages] = []
25 25 end
26 26 result
... ...
app/controllers/profiles/groups_controller.rb
... ... @@ -2,7 +2,7 @@ class Profiles::GroupsController &lt; ApplicationController
2 2 layout "profile"
3 3  
4 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 6 end
7 7  
8 8 def leave
... ...
app/controllers/projects/branches_controller.rb
... ... @@ -11,6 +11,10 @@ class Projects::BranchesController &lt; Projects::ApplicationController
11 11 @branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30)
12 12 end
13 13  
  14 + def recent
  15 + @branches = @repository.recent_branches
  16 + end
  17 +
14 18 def create
15 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 10 before_filter :edit_requirements, only: [:show, :update]
11 11  
12 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 14 end
15 15  
16 16 def update
... ...
app/controllers/projects/repositories_controller.rb
... ... @@ -4,10 +4,6 @@ class Projects::RepositoriesController &lt; Projects::ApplicationController
4 4 before_filter :authorize_code_access!
5 5 before_filter :require_non_empty_project
6 6  
7   - def show
8   - @activities = @repository.commits_with_refs(20)
9   - end
10   -
11 7 def stats
12 8 @stats = Gitlab::Git::Stats.new(@repository.raw, @repository.root_ref)
13 9 @graph = @stats.graph
... ...
app/controllers/users_groups_controller.rb
... ... @@ -13,7 +13,8 @@ class UsersGroupsController &lt; ApplicationController
13 13 end
14 14  
15 15 def update
16   - # TODO: implement
  16 + @member = @group.users_groups.find(params[:id])
  17 + @member.update_attributes(params[:users_group])
17 18 end
18 19  
19 20 def destroy
... ...
app/helpers/commits_helper.rb
... ... @@ -15,61 +15,9 @@ module CommitsHelper
15 15 commit_person_link(commit, options.merge(source: :committer))
16 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 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 21 end
74 22 end
75 23  
... ...
app/helpers/dashboard_helper.rb
1 1 module DashboardHelper
2   - def dashboard_filter_path(entity, options={})
  2 + def filter_path(entity, options={})
3 3 exist_opts = {
4 4 status: params[:status],
5 5 project_id: params[:project_id],
... ... @@ -7,12 +7,9 @@ module DashboardHelper
7 7  
8 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 13 end
17 14  
18 15 def entities_per_project project, entity
... ...
app/helpers/groups_helper.rb
1 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 2 def remove_user_from_group_message(group, user)
19 3 "You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
20 4 end
... ...
app/helpers/notifications_helper.rb
1 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 13 end
... ...
app/helpers/tree_helper.rb
... ... @@ -39,12 +39,12 @@ module TreeHelper
39 39 #
40 40 # Returns boolean
41 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 44 end
45 45  
46 46 def gitlab_markdown?(filename)
47   - filename.end_with?(*%w(.mdown .md .markdown))
  47 + filename.downcase.end_with?(*%w(.mdown .md .markdown))
48 48 end
49 49  
50 50 def plain_text_readme? filename
... ... @@ -57,6 +57,8 @@ module TreeHelper
57 57 end
58 58  
59 59 def allowed_tree_edit?
  60 + return false unless @repository.branch_names.include?(@ref)
  61 +
60 62 if @project.protected_branch? @ref
61 63 can?(current_user, :push_code_to_protected_branches, @project)
62 64 else
... ...
app/models/deprecated/user_team.rb
  1 +# Will be removed in 6.1 with tables
  2 +#
1 3 # == Schema Information
2 4 #
3 5 # Table name: user_teams
... ...
app/models/deprecated/user_team_project_relationship.rb
  1 +# Will be removed in 6.1 with tables
  2 +#
1 3 # == Schema Information
2 4 #
3 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 3 # == Schema Information
2 4 #
3 5 # Table name: user_team_user_relationships
... ...
app/models/merge_request.rb
... ... @@ -149,11 +149,12 @@ class MergeRequest &lt; ActiveRecord::Base
149 149 end
150 150  
151 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 158 diffs ||= []
158 159 diffs
159 160 end
... ...
app/models/note.rb
... ... @@ -50,6 +50,9 @@ class Note &lt; ActiveRecord::Base
50 50 scope :inc_author_project, ->{ includes(:project, :author) }
51 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 56 def self.create_status_change_note(noteable, project, author, status)
54 57 create({
55 58 noteable: noteable,
... ... @@ -67,28 +70,61 @@ class Note &lt; ActiveRecord::Base
67 70 nil
68 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 78 end
78 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 100 def diff_file_index
81 101 line_code.split('_')[0]
82 102 end
83 103  
84 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 110 end
87 111  
88 112 def diff_new_line
89 113 line_code.split('_')[2].to_i
90 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 128 def discussion_id
93 129 @discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym
94 130 end
... ...
app/models/repository.rb
... ... @@ -18,19 +18,25 @@ class Repository
18 18 end
19 19  
20 20 def commit(id = nil)
21   - commit = raw_repository.commit(id)
  21 + commit = Gitlab::Git::Commit.find(raw_repository, id)
22 22 commit = Commit.new(commit) if commit
23 23 commit
24 24 end
25 25  
26 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 34 commits = Commit.decorate(commits) if commits.present?
29 35 commits
30 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 40 commits = Commit.decorate(commits) if commits.present?
35 41 commits
36 42 end
... ... @@ -43,6 +49,12 @@ class Repository
43 49 tags.find { |tag| tag.name == name }
44 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 58 def add_branch(branch_name, ref)
47 59 Rails.cache.delete(cache_key(:branch_names))
48 60  
... ...
app/services/notification_service.rb
... ... @@ -102,19 +102,22 @@ class NotificationService
102 102 # ignore wall messages
103 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 108 opts = { noteable_type: note.noteable_type, project_id: note.project_id }
106 109  
107 110 if note.commit_id.present?
108 111 opts.merge!(commit_id: note.commit_id)
109   - recipients = [note.commit_author]
110 112 else
111 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 121 end
119 122  
120 123 # Get users who left comment in thread
... ...
app/views/admin/groups/edit.html.haml
... ... @@ -4,22 +4,22 @@
4 4 - if @group.errors.any?
5 5 .alert.alert-error
6 6 %span= @group.errors.full_messages.first
7   - .clearfix.group_name_holder
  7 + .control-group.group_name_holder
8 8 = f.label :name do
9 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 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 19 = f.label :path do
20 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 23 %ul.cred
24 24 %li Changing group path can have unintended side effects.
25 25 %li Renaming group path will rename directory for all related projects
... ...
app/views/admin/groups/index.html.haml
... ... @@ -4,7 +4,7 @@
4 4 allows you to keep projects organized.
5 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 8 %br
9 9 = form_tag admin_groups_path, method: :get, class: 'form-inline' do
10 10 = text_field_tag :name, params[:name], class: "span6"
... ...
app/views/admin/groups/new.html.haml
... ... @@ -4,15 +4,15 @@
4 4 - if @group.errors.any?
5 5 .alert.alert-error
6 6 %span= @group.errors.full_messages.first
7   - .clearfix
  7 + .control-group
8 8 = f.label :name do
9 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 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 17 .form-actions
18 18 = f.submit 'Create group', class: "btn btn-create"
... ...
app/views/admin/hooks/index.html.haml
... ... @@ -10,10 +10,10 @@
10 10 .alert.alert-error
11 11 - @hook.errors.full_messages.each do |msg|
12 12 %p= msg
13   - .clearfix
  13 + .control-group
14 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 17 &nbsp;
18 18 = f.submit "Add System Hook", class: "btn btn-create"
19 19 %hr
... ...
app/views/admin/projects/index.html.haml
... ... @@ -38,7 +38,7 @@
38 38 .title
39 39 Projects (#{@projects.total_count})
40 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 42 %ul.well-list
43 43 - @projects.each do |project|
44 44 %li
... ...
app/views/admin/users/_form.html.haml
... ... @@ -8,28 +8,28 @@
8 8  
9 9 %fieldset
10 10 %legend Account
11   - .clearfix
  11 + .control-group
12 12 = f.label :name
13   - .input
  13 + .controls
14 14 = f.text_field :name, required: true, autocomplete: "off"
15 15 %span.help-inline * required
16   - .clearfix
  16 + .control-group
17 17 = f.label :username
18   - .input
  18 + .controls
19 19 = f.text_field :username, required: true, autocomplete: "off"
20 20 %span.help-inline * required
21   - .clearfix
  21 + .control-group
22 22 = f.label :email
23   - .input
  23 + .controls
24 24 = f.text_field :email, required: true, autocomplete: "off"
25 25 %span.help-inline * required
26 26  
27 27 - if @user.new_record?
28 28 %fieldset
29 29 %legend Password
30   - .clearfix
  30 + .control-group
31 31 = f.label :password
32   - .input
  32 + .controls
33 33 %strong
34 34 A temporary password will be generated and sent to user.
35 35 %br
... ... @@ -37,33 +37,33 @@
37 37 - else
38 38 %fieldset
39 39 %legend Password
40   - .clearfix
  40 + .control-group
41 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 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 47 %fieldset
48 48 %legend Access
49 49 .row
50 50 .span8
51   - .clearfix
  51 + .control-group
52 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 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 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 64 = f.label :admin do
65 65 %strong.cred Administrator
66   - .input= f.check_box :admin
  66 + .controls= f.check_box :admin
67 67 .span4
68 68 - unless @user.new_record?
69 69 .alert.alert-error
... ... @@ -75,17 +75,17 @@
75 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 76 %fieldset
77 77 %legend Profile
78   - .clearfix
  78 + .control-group
79 79 = f.label :skype
80   - .input= f.text_field :skype
81   - .clearfix
  80 + .controls= f.text_field :skype
  81 + .control-group
82 82 = f.label :linkedin
83   - .input= f.text_field :linkedin
84   - .clearfix
  83 + .controls= f.text_field :linkedin
  84 + .control-group
85 85 = f.label :twitter
86   - .input= f.text_field :twitter
  86 + .controls= f.text_field :twitter
87 87  
88   - .actions
  88 + .form-actions
89 89 - if @user.new_record?
90 90 = f.submit 'Create user', class: "btn btn-create"
91 91 = link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
... ...
app/views/admin/users/index.html.haml
... ... @@ -30,7 +30,7 @@
30 30 .title
31 31 Users (#{@users.total_count})
32 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 34 %ul.well-list
35 35 - @users.each do |user|
36 36 %li
... ... @@ -55,4 +55,4 @@
55 55 - else
56 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 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   -= 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 1 %h3.page-title
2   - Issues
3   - %span.light
4   - &ndash;
5   - Assigned to you
  2 + Issues assigned to me
6 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 9 .row
9 10 .span3
10   - = render 'filter', entity: 'issue'
  11 + = render 'shared/filter', entity: 'issue'
11 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 1 %h3.page-title
2 2 Merge Requests
3   - %span.light
4   - &ndash;
5   - Authored by or assigned to you
6 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 9 .row
9 10 .span3
10   - = render 'filter', entity: 'merge_request'
  11 + = render 'shared/filter', entity: 'merge_request'
11 12 .span9
12 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 5 .row
2 6 .span3
3 7 %ul.nav.nav-pills.nav-stacked
... ... @@ -32,7 +36,7 @@
32 36 = label.name
33 37  
34 38 .span9
35   - %ul.bordered-list.my-projects
  39 + %ul.bordered-list.my-projects.top-list
36 40 - @projects.each do |project|
37 41 %li
38 42 %h4.project-title
... ...
app/views/groups/_new_group_member.html.haml
1 1 = form_for @users_group, url: group_users_groups_path(@group) do |f|
2 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 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 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 18 .form-actions
16 19 = f.submit 'Add users into group', class: "btn btn-create"
... ...
app/views/groups/edit.html.haml
... ... @@ -20,22 +20,22 @@
20 20 .ui-box
21 21 .title
22 22 %strong= @group.name
23   - Group Settings:
  23 + group settings:
24 24 %div.form-holder
25 25 = form_for @group do |f|
26 26 - if @group.errors.any?
27 27 .alert.alert-error
28 28 %span= @group.errors.full_messages.first
29   - .clearfix
  29 + .control-group
30 30 = f.label :name do
31 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 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 40 .form-actions
41 41 = f.submit 'Save group', class: "btn btn-save"
... ... @@ -44,7 +44,7 @@
44 44 .ui-box
45 45 .title
46 46 %strong= @group.name
47   - Projects:
  47 + projects:
48 48 - if can? current_user, :manage_group, @group
49 49 %span.pull-right
50 50 = link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny" do
... ... @@ -85,4 +85,4 @@
85 85 %p
86 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 6 %hr
7 7 .row
8 8 .span3
9   - = render 'filter', entity: 'issue'
  9 + = render 'shared/filter', entity: 'issue'
10 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 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 %hr
7 7 .row
8 8 .span3
9   - = render 'filter', entity: 'merge_request'
  9 + = render 'shared/filter', entity: 'merge_request'
10 10 .span9
11 11 = render 'shared/merge_requests'
... ...
app/views/groups/new.html.haml
... ... @@ -2,19 +2,19 @@
2 2 - if @group.errors.any?
3 3 .alert.alert-error
4 4 %span= @group.errors.full_messages.first
5   - .clearfix
  5 + .control-group
6 6 = f.label :name do
7 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 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 18 %ul
19 19 %li Group is kind of directory for several projects
20 20 %li All created groups are private
... ...
app/views/help/index.html.haml
... ... @@ -8,8 +8,6 @@
8 8 %br
9 9 Fast, secure and stable solution based on Ruby on Rails.
10 10  
11   -%br
12   -
13 11 .row
14 12 .span4
15 13 .ui-box
... ...
app/views/notify/new_user_email.html.haml
... ... @@ -4,7 +4,7 @@
4 4 - if Gitlab.config.gitlab.signup_enabled
5 5 Your account has been created successfully.
6 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 8 %p
9 9 login..........................................
10 10 %code= @user['email']
... ...
app/views/notify/new_user_email.text.erb
1 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 5 login.................. <%= @user.email %>
6 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 8 - unless current_user.ldap_user?
2 9 - if Gitlab.config.omniauth.enabled
3 10 %fieldset
... ... @@ -20,15 +27,15 @@
20 27 - @user.errors.full_messages.each do |msg|
21 28 %li= msg
22 29  
23   - .clearfix
  30 + .control-group
24 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 34 = f.label :password_confirmation
28   - .input
  35 + .controls
29 36 = f.password_field :password_confirmation, required: true
30   - .clearfix
31   - .input
  37 + .control-group
  38 + .controls
32 39 = f.submit 'Save password', class: "btn btn-save"
33 40  
34 41  
... ... @@ -47,7 +54,7 @@
47 54 It can be used for atom feed or API
48 55 %p.cgray
49 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 58 = f.submit 'Reset', confirm: "Are you sure?", class: "btn btn-primary btn-build-token"
52 59 - else
53 60 %span You don`t have one yet. Click generate to fix it.
... ... @@ -63,7 +70,7 @@
63 70 = form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
64 71 .padded
65 72 = f.label :username
66   - .input
  73 + .controls
67 74 = f.text_field :username, required: true
68 75 &nbsp;
69 76 %span.loading-gif.hide= image_tag "ajax_loader.gif"
... ... @@ -76,7 +83,7 @@
76 83 %ul.cred
77 84 %li It will change web url for personal projects.
78 85 %li It will change the git path to repositories for personal projects.
79   - .input
  86 + .controls
80 87 = f.submit 'Save username', class: "btn btn-save"
81 88  
82 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 7 = form_for @user, url: profile_path, remote: true, method: :put do |f|
2 8 %fieldset.application-theme
3 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 11 .ui-box
2 12 .title
3 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 15 %ul.well-list
11   - - @groups.each do |group|
  16 + - @user_groups.each do |user_group|
  17 + - group = user_group.group
12 18 %li
13 19 .pull-right
14 20 - if can?(current_user, :manage_group, group)
... ... @@ -23,4 +29,7 @@
23 29 = link_to group, class: 'group-name' do
24 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 6 .profile_history
2 7 = render @events
3 8 %hr
... ...
app/views/profiles/keys/_form.html.haml
... ... @@ -6,18 +6,18 @@
6 6 - @key.errors.full_messages.each do |msg|
7 7 %li= msg
8 8  
9   - .clearfix
  9 + .control-group
10 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 13 = f.label :key
14   - .input
  14 + .controls
15 15 %p.light
16 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 21 = f.submit 'Add key', class: "btn btn-create"
22 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 5 %p.light
2 6 SSH key allows you to establish a secure connection between your computer and GitLab
3   -%p.light
  7 + %br
4 8 Before you can add ssh key you need to
5 9 = link_to "generate it", help_ssh_path
6   -
  10 +%hr
7 11  
8 12  
9 13 .ui-box
10 14 .title
11 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 16 %ul.well-list#keys-table
15 17 = render @keys
16 18 - if @keys.blank?
... ...
app/views/profiles/notifications/_settings.html.haml
... ... @@ -2,6 +2,8 @@
2 2 .row
3 3 .span4
4 4 %span
  5 + = notification_icon(notification)
  6 +
5 7 - if membership.kind_of? UsersGroup
6 8 = link_to membership.group.name, membership.group
7 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 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 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 20 .row
15 21 .span4
16   - %h5 Global setting
  22 + %h4
  23 + = notification_icon(@notification)
  24 + Global setting
17 25 .span7
18 26 = form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
19 27 = hidden_field_tag :notification_type, 'global'
... ... @@ -30,20 +38,21 @@
30 38 = radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit'
31 39 %span Watch
32 40  
33   -%hr
  41 +%br
34 42 = link_to '#', class: 'js-toggle-visibility-link' do
35   - %h6.btn.btn-tiny
  43 + %span.btn.btn-tiny
36 44 %i.icon-chevron-down
37 45 %span Advanced notifications settings
38 46 .js-toggle-visibility-container.hide
39   - %h5 Groups:
40   - %ul.well-list
  47 + %hr
  48 + %h4 Groups:
  49 + %ul.bordered-list
41 50 - @users_groups.each do |users_group|
42 51 - notification = Notification.new(users_group)
43 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 56 - @users_projects.each do |users_project|
48 57 - notification = Notification.new(users_project)
49 58 = render 'settings', type: 'project', membership: users_project, notification: notification
... ...
app/views/profiles/passwords/new.html.haml
... ... @@ -10,13 +10,13 @@
10 10 - @user.errors.full_messages.each do |msg|
11 11 %li= msg
12 12  
13   - .clearfix
  13 + .control-group
14 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 17 = f.label :password_confirmation
18   - .input
  18 + .controls
19 19 = f.password_field :password_confirmation, required: true
20   - .clearfix
21   - .input
  20 + .control-group
  21 + .controls
22 22 = f.submit 'Set new password', class: "btn btn-create"
... ...
app/views/profiles/show.html.haml
... ... @@ -87,4 +87,4 @@
87 87 = link_to "Add Public Key", new_profile_key_path, class: "btn btn-small"
88 88  
89 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   -%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 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 4 .file-holder
15 5 .file-title
16 6 %i.icon-file
17 7 %span.file_name
18   - = @blob.name
  8 + = @path
19 9 %small= number_to_human_size @blob.size
20 10 %span.options= render "projects/blob/actions"
21 11 .file-content.blame
... ...
app/views/projects/blob/_actions.html.haml
1 1 .btn-group.tree-btn-group
2 2 -# only show edit link for text files
3 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 6 -# only show normal/blame view links for text files
7 7 - if @blob.text?
8 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 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 @@
  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 1 = render "projects/commits/head"
2 2 .row
3 3 .span3
4   - = render "projects/repositories/filter"
  4 + = render "filter"
5 5 .span9
6 6 - unless @branches.empty?
7 7 %ul.bordered-list
... ...
app/views/projects/branches/recent.html.haml 0 → 100644
... ... @@ -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 = link_to 'Compare', project_compare_index_path(@project)
8 8  
9 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 11 Branches
12 12 %span.badge= @repository.branches.length
13 13  
... ...
app/views/projects/commits/_text_file.html.haml
... ... @@ -3,7 +3,7 @@
3 3 %a.supp_diff_link Diff suppressed. Click to show
4 4  
5 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 7 %tr.line_holder{ id: line_code, class: "#{type}" }
8 8 - if type == "match"
9 9 %td.old_line= "..."
... ... @@ -20,4 +20,4 @@
20 20 - if @reply_allowed
21 21 - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
22 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 1 = render "head"
2 2  
3 3 - if @path.present?
4   - %ul.breadcrumb
  4 + %ul.breadcrumb.commit-breadcrumb
5 5 %li.light
6 6 History for
7 7 = commits_breadcrumbs
... ...
app/views/projects/compare/_form.html.haml
... ... @@ -14,9 +14,9 @@
14 14 .pull-left
15 15 - if params[:to] && params[:from]
16 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 20 .pull-left
21 21 &nbsp;
22 22 = submit_tag "Compare", class: "btn btn-create commits-compare-btn"
... ...
app/views/projects/create.js.haml
... ... @@ -4,5 +4,6 @@
4 4 - else
5 5 :plain
6 6 $(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
  7 + $('.project-submit').enable();
7 8 $('.save-project-loader').hide();
8 9 $('.project-edit-container').show();
... ...
app/views/projects/deploy_keys/_form.html.haml
... ... @@ -6,18 +6,18 @@
6 6 - @key.errors.full_messages.each do |msg|
7 7 %li= msg
8 8  
9   - .clearfix
  9 + .control-group
10 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 13 = f.label :key
14   - .input
15   - = f.text_area :key, class: [:xxlarge, :thin_area]
16   - %p.hint
  14 + .controls
  15 + %p.light
17 16 Paste a machine public key here. Read more about how generate it
18 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 21 = f.submit 'Create', class: "btn-create btn"
22 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 5 %i.icon-plus
8 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 12 %hr.clearfix
11 13  
12 14 .row
13 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 19 %ul.bordered-list
18 20 = render @enabled_keys
19 21 - if @enabled_keys.blank?
... ... @@ -21,10 +23,10 @@
21 23 %p.nothing_here_message Create #{link_to 'new deploy key', new_project_deploy_key_path(@project)} or add existing one
22 24 .span5.available-keys
23 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 28 %ul.bordered-list
27 29 = render @available_keys
28 30 - if @available_keys.blank?
29 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 4 .ui-box.white
5 5 .title
6 6 %strong= @project.name
7   - Project Settings:
  7 + project settings:
8 8 .form-holder
9 9 = form_for(@project, remote: true) do |f|
10 10 %fieldset
11   - .clearfix.project_name_holder
  11 + .control-group.project_name_holder
12 12 = f.label :name do
13 13 Project name is
14   - .input
  14 + .controls
15 15 = f.text_field :name, placeholder: "Example Project", class: "span5"
16 16  
17 17  
18   - .clearfix
  18 + .control-group
19 19 = f.label :description do
20 20 Project description
21 21 %span.light (optional)
22   - .input
  22 + .controls
23 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 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 31 - if can?(current_user, :change_public_mode, @project)
... ... @@ -66,11 +66,11 @@
66 66 - if Project.issues_tracker.values.count > 1
67 67 .control-group
68 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 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 75 .control-group
76 76 = f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
... ... @@ -98,7 +98,7 @@
98 98  
99 99  
100 100 .form-actions
101   - = f.submit 'Save', class: "btn btn-save"
  101 + = f.submit 'Save changes', class: "btn btn-save"
102 102  
103 103 - if can?(current_user, :change_namespace, @project)
104 104 .ui-box.ui-box-danger
... ... @@ -110,7 +110,7 @@
110 110 = f.label :namespace_id do
111 111 %span Namespace
112 112 .controls
113   - .clearfix
  113 + .control-group
114 114 = f.select :namespace_id, namespaces_options(@project.namespace_id), {prompt: 'Choose a project namespace'}, {class: 'chosen'}
115 115 %ul
116 116 %li Be careful. Changing project namespace can have unintended side effects
... ... @@ -130,7 +130,7 @@
130 130 = f.label :path do
131 131 %span Path
132 132 .controls
133   - .clearfix
  133 + .control-group
134 134 = f.text_field :path
135 135 %ul
136 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 2 .file-editor
2 3 = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
3 4 .file-holder
... ...
app/views/projects/hooks/index.html.haml
... ... @@ -11,10 +11,10 @@
11 11 .alert.alert-error
12 12 - @hook.errors.full_messages.each do |msg|
13 13 %p= msg
14   - .clearfix
  14 + .control-group
15 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 18 &nbsp;
19 19 = f.submit "Add Web Hook", class: "btn btn-create"
20 20 %hr
... ...
app/views/projects/issues/_filter.html.haml
... ... @@ -18,6 +18,9 @@
18 18 All
19 19  
20 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  
... ...