Commit 4537623d authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

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