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/*
rails_best_practices_output.html
doc/code/*
.secret
*.log
public/uploads.*
......@@ -2,6 +2,12 @@
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
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'
# Extracting information from a git repository
# 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
gem 'gitlab-grack', '~> 1.0.1', require: 'grack'
......
......@@ -176,7 +176,7 @@ GEM
gitlab-pygments.rb (0.3.2)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
gitlab_git (1.4.1)
gitlab_git (2.0.0.pre)
activesupport (~> 3.2.13)
github-linguist (~> 2.3.4)
gitlab-grit (~> 2.6.0)
......@@ -275,7 +275,7 @@ GEM
minitest (4.7.4)
modernizr (2.6.2)
sprockets (~> 2.0)
multi_json (1.7.7)
multi_json (1.7.8)
multi_xml (0.5.4)
multipart-post (1.2.0)
mysql2 (0.3.11)
......@@ -568,7 +568,7 @@ DEPENDENCIES
gitlab-gollum-lib (~> 1.0.1)
gitlab-grack (~> 1.0.1)
gitlab-pygments.rb (~> 0.3.2)
gitlab_git (~> 1.4.1)
gitlab_git (~> 2.0.0.pre)
gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.3)
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
* [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.
* [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 @@ $ ->
container = $(".js-toggle-visibility-container")
container.toggleClass("hide")
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
cuday = 0
cumonth = ""
r.rect(0, 0, 26, @barHeight).attr fill: "#222"
r.rect(26, 0, 20, @barHeight).attr fill: "#444"
r.rect(0, 0, 40, @barHeight).attr fill: "#222"
r.rect(40, 0, 30, @barHeight).attr fill: "#444"
for day, mm in @days
if cuday isnt day[0]
# Dates
r.text(36, @offsetY + @unitTime * mm, day[0])
r.text(55, @offsetY + @unitTime * mm, day[0])
.attr(
font: "12px Monaco, monospace"
fill: "#DDD"
fill: "#BBB"
)
cuday = day[0]
if cumonth isnt day[1]
# Months
r.text(13, @offsetY + @unitTime * mm, day[1])
r.text(20, @offsetY + @unitTime * mm, day[1])
.attr(
font: "12px Monaco, monospace"
fill: "#EEE"
......
......@@ -39,7 +39,9 @@ class Dispatcher
switch path.first()
when 'admin' then new Admin()
when 'wikis' then new Wikis()
when 'projects'
new Wikis() if path[1] == 'wikis'
initSearch: ->
autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts')
......
......@@ -7,3 +7,7 @@ $.fn.enableButton = ->
$(@).removeAttr('disabled').
removeClass('disabled')
$.fn.disableButton = ->
$(@).attr('disabled', 'disabled').
addClass('disabled')
......@@ -44,7 +44,7 @@ GitLab.GfmAutoComplete =
tpl: @Issues.template
callbacks:
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", =>
$.getJSON(@dataSource).done (data) ->
......
......@@ -119,7 +119,7 @@ $ ->
# Commit show suppressed diff
$(".supp_diff_link").bind "click", ->
$(".content").on "click", ".supp_diff_link", ->
$(@).next('table').show()
$(@).remove()
......
......@@ -22,12 +22,7 @@ class MergeRequest
this.$('.show-all-commits').on 'click', =>
this.showAllCommits()
modal = $('#modal_merge_info').modal modal: true, show:false
$('.how_to_merge_link').bind "click", ->
modal.show()
$('.modal-header .close').bind "click", ->
modal.hide()
modal = $('#modal_merge_info').modal(show: false)
# Local jQuery finder
$: (selector) ->
......
......@@ -227,10 +227,11 @@ var NoteList = {
// Show the attachment delete link
note.find(".js-note-attachment-delete").show();
GitLab.GfmAutoComplete.setup();
var form = note.find(".note-edit-form");
form.show();
var textarea = form.find("textarea");
var p = $("<p></p>").text(textarea.val());
var hidden_div = $('<div class="note-original-content"></div>').append(p);
......
class Wikis
constructor: ->
modal = $('#modal-new-wiki').modal({modal: true, show:false})
$('.add-new-wiki').bind "click", ->
modal.show()
$('.build-new-wiki').bind "click", ->
field = $('#new_wiki_path')
slug = field.val()
......@@ -13,7 +8,5 @@ class Wikis
if(slug.length > 0)
location.href = path + "/" + slug
$('.modal-header .close').bind "click", ->
modal.hide()
@Wikis = Wikis
......@@ -81,33 +81,6 @@ span.update-author {
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 {
display: inline;
}
......@@ -121,15 +94,6 @@ ul.breadcrumb {
}
a {
color: #474D57;
font-weight: bold;
font-size: 14px;
}
}
input[type=text] {
&.large_text {
padding: 6px;
font-size: 16px;
}
}
......
......@@ -2,11 +2,49 @@
$baseFontSize: 13px !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-1200px-min";
/**
* Font icons
*
*/
@import "font-awesome";
/**
......@@ -26,3 +64,4 @@ $baseLineHeight: 18px !default;
@import "gitlab_bootstrap/files.scss";
@import "gitlab_bootstrap/tables.scss";
@import "gitlab_bootstrap/lists.scss";
@import "gitlab_bootstrap/forms.scss";
......@@ -10,15 +10,34 @@
*
*/
.ui-box {
background: #F9F9F9;
background: #FFF;
margin-bottom: 20px;
border: 1px solid #CCC;
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 {
margin:20px 0;
background: #FFF;
.control-group {
margin-bottom: 0;
}
}
&.ui-box-danger {
......@@ -71,10 +90,6 @@
border-top: 1px solid #eee;
}
&.white {
background: #fff;
}
ul {
margin: 0;
}
......@@ -102,6 +117,8 @@
.btn {
vertical-align: middle;
padding: 4px 12px;
@include box-shadow(0 0px 1px 1px #f2f2f2);
}
.nav-pills {
......
.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);
text-shadow: 0 1px 1px #FFF;
border-color: #BBB;
text-decoration: none;
&.hover,
&:hover {
color: $style_color;
background: #f1f1f1;
@include linear-gradient(#fAfAfA, #f1f1f1);
border-color: #AAA;
color: #333;
text-decoration: none;
@include linear-gradient(#fAfAfA, #f1f1f1);
}
&.btn-primary {
background: #2a79A3;
@include linear-gradient(#47A7b7, #2585b5);
border-color: #2A79A3;
color: #fff;
text-shadow: 0 1px 1px #268;
&:hover {
background: $primary_color;
color: #fff;
&.focus,
&:focus {
text-decoration: none;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
&.disabled {
color: #fff;
background: $primary_color;
}
&.active,
&:active {
background-image: none;
outline: 0;
text-decoration: none;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
&.btn-info {
background: #5aB9C3;
border-color: $primary_color;
color: #fff;
text-shadow: 0 1px 1px #268;
&:hover {
background: $primary_color;
color: #fff;
&.disabled,
&[disabled] {
cursor: default;
background-image: none;
@include opacity(65);
@include box-shadow(none);
}
&.disabled {
color: #fff;
background: $primary_color;
&.btn-primary {
color: #FFF;
border-color: #189;
text-shadow: 0 1px 1px #189;
@include linear-gradient(#4AC, #289);
&.hover,
&:hover,
&.disabled,
&[disabled] {
color: #FFF;
background: #389;
}
}
&.btn-success {
&:hover {
background: #51a351;
color: #FFF;
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 {
color: #fff;
background: #2b2;
&.btn-danger {
color: #FFF;
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 {
@extend .wide;
@extend .btn-success;
......@@ -67,12 +111,6 @@
&.btn-close,
&.btn-remove {
@extend .btn-danger;
border-color: #BD362F;
&:hover {
color: #fff;
background: #EE4E49;
}
}
&.btn-cancel {
......@@ -84,13 +122,9 @@
padding-right: 20px;
}
&.small {
@extend .btn-small;
}
&.active {
border-color: #aaa;
background-color: #ccc;
&.btn-small {
padding: 2px 10px;
font-size: 12px;
}
&.btn-tiny {
......@@ -104,9 +138,4 @@
margin-right: 7px;
float: left;
}
&.padded {
margin-right: 3px;
padding: 4px 10px 4px;
}
}
......@@ -48,7 +48,13 @@
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 **/
input[type='search'].search-text-input {
......@@ -66,7 +72,7 @@ input[type='text'].danger {
text-shadow: 0 1px 1px #fff
}
fieldset legend { font-size: 17px; }
fieldset legend { font-size: 15px; }
.tab-content {
overflow: visible;
......@@ -90,3 +96,11 @@ pre.well-pre {
border-radius: 0;
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 @@
*
*/
.file-holder {
border: 1px solid #BBB;
border: 1px solid #CCC;
margin-bottom: 1em;
@include solid-shade;
.file-title {
border-bottom: 1px solid #bbb;
@include bg-dark-gray-gradient;
text-shadow: 0 1px 1px #fff;
margin: 0;
font-weight: normal;
font-weight: bold;
text-align: left;
color: #666;
color: $style_color;
padding: 9px 10px;
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 @@
margin: 0;
list-style: none;
li {
background-color: #FFF;
padding: 10px;
min-height: 20px;
border-bottom: 1px solid #eee;
......@@ -84,4 +83,13 @@ ul.bordered-list {
a { color: #777; }
}
}
&.top-list {
li:first-child {
padding-top: 0;
h4, h5 {
margin-top: 0;
}
}
}
}
......@@ -90,7 +90,6 @@
@mixin page-title {
color: $style_color;
font-size: 20px;
font-weight: normal;
line-height: 1.5;
margin-top: 0px;
margin-bottom: 15px;
......
......@@ -10,6 +10,7 @@
> li > a {
@include border-radius(0);
}
&.nav-stacked {
> li > a {
border-left: 4px solid #EEE;
......@@ -30,6 +31,12 @@
}
}
}
&.nav-pills-small {
> li > a {
padding: 8px 12px;
}
}
}
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
......
table {
@extend .table;
@extend .table-striped;
@include solid-shade;
border: 1px solid #bbb;
border: 1px solid #CCC;
width: 100%;
&.low {
......@@ -20,7 +19,7 @@ table {
th {
font-weight: bold;
vertical-align: middle;
border-bottom: 1px solid #bbb;
border-bottom: 1px solid #CCC;
text-shadow: 0 1px 1px #fff;
@include bg-dark-gray-gradient;
......@@ -46,11 +45,11 @@ table {
}
&:first-child {
border-left: 1px solid #bbb;
border-left: 1px solid #CCC;
}
&:last-child {
border-right: 1px solid #bbb;
border-right: 1px solid #CCC;
}
}
......
......@@ -2,6 +2,10 @@
* Headers
*
*/
h1, h2, h3, h4, h5, h6 {
font-weight: 500;
line-height: 1.1;
}
h1.page-title {
@include page-title;
......@@ -48,13 +52,6 @@ a {
text-decoration: underline;
}
&.btn {
color: $style_color;
&:hover {
color: $style_color;
}
}
&.dark {
color: $style_color;
}
......
......@@ -421,8 +421,8 @@
.commits-compare-switch{
background: url("switch_icon.png") no-repeat center center;
width: 16px;
height: 18px;
width: 22px;
height: 22px;
text-indent: -9999px;
float: left;
margin-right: 9px;
......@@ -471,3 +471,7 @@ li.commit {
}
}
}
.commit-breadcrumb {
padding: 0;
}
......@@ -44,7 +44,7 @@ input.check_all_issues {
margin: 0;
margin-right: 10px;
position: relative;
top: 8px;
top: 10px;
height: 22px;
}
......@@ -52,6 +52,10 @@ input.check_all_issues {
.title {
height: 40px;
}
form {
margin: 0;
}
}
.btn.close_issue {
......@@ -88,14 +92,11 @@ input.check_all_issues {
}
.update_selected_issues {
position: relative;
top:5px;
margin-left: 4px;
float: left;
}
.update_issues_text {
padding: 3px;
padding: 5px;
line-height: 28px;
float: left;
color: #479;
......
......@@ -7,7 +7,7 @@
ul {
margin: auto;
height: 42px;
height: 40px;
overflow: hidden;
.count {
font-weight: normal;
......@@ -74,7 +74,7 @@
text-align: center;
font-weight: normal;
height: 38px;
line-height: 36px;
line-height: 34px;
color: #777;
text-shadow: 0 1px 1px white;
padding: 0 10px;
......
.new_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 {
.control-label {
font-weight: bold;
......@@ -30,6 +13,10 @@
padding: 4px 7px;
border: 1px solid #CCC;
margin-bottom: 20px;
.btn {
padding: 4px 12px;
}
}
.project_clone_holder {
......@@ -114,7 +101,7 @@ ul.nav.nav-projects-tabs {
.public-clone {
background: #333;
color: #f5f5f5;
padding: 5px 10px;
padding: 6px 10px;
margin: 1px;
font-weight: normal;
}
......
......@@ -104,6 +104,8 @@
}
.tree-btn-group {
top: 2px;
.btn {
margin-right: 0px;
padding: 2px 10px;
......
......@@ -31,8 +31,4 @@
border-left: 1px solid #666;
}
}
.main-nav {
box-shadow: 0 -1px 0 white inset;
}
}
......@@ -11,8 +11,8 @@ class FilterContext
end
def apply_filter items
if params[:project_id]
items = items.by_project(params[:project_id])
if params[:project_id].present?
items = items.where(project_id: params[:project_id])
end
if params[:search].present?
......
......@@ -2,7 +2,7 @@
# based on filtering passed via params for @project
class MergeRequestsLoadContext < BaseContext
def execute
type = params[:f]
type = params[:status]
merge_requests = project.merge_requests
......
......@@ -11,7 +11,7 @@ class SearchContext
return result unless query.present?
projects = Project.where(id: project_ids)
result[:projects] = projects.search(query).limit(10)
result[:projects] = projects.search(query).limit(20)
# Search inside singe project
project = projects.first if projects.length == 1
......@@ -19,8 +19,8 @@ class SearchContext
if params[:search_code].present?
result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo?
else
result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).limit(10)
result[:issues] = Issue.where(project_id: 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(20)
result[:wiki_pages] = []
end
result
......
......@@ -2,7 +2,7 @@ class Profiles::GroupsController < ApplicationController
layout "profile"
def index
@groups = current_user.authorized_groups.page(params[:page]).per(20)
@user_groups = current_user.users_groups.page(params[:page]).per(20)
end
def leave
......
......@@ -11,6 +11,10 @@ class Projects::BranchesController < Projects::ApplicationController
@branches = Kaminari.paginate_array(@repository.branches).page(params[:page]).per(30)
end
def recent
@branches = @repository.recent_branches
end
def create
@repository.add_branch(params[:branch_name], params[:ref])
......
......@@ -10,7 +10,7 @@ class Projects::EditTreeController < Projects::ApplicationController
before_filter :edit_requirements, only: [:show, :update]
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
def update
......
......@@ -4,10 +4,6 @@ class Projects::RepositoriesController < Projects::ApplicationController
before_filter :authorize_code_access!
before_filter :require_non_empty_project
def show
@activities = @repository.commits_with_refs(20)
end
def stats
@stats = Gitlab::Git::Stats.new(@repository.raw, @repository.root_ref)
@graph = @stats.graph
......
......@@ -13,7 +13,8 @@ class UsersGroupsController < ApplicationController
end
def update
# TODO: implement
@member = @group.users_groups.find(params[:id])
@member.update_attributes(params[:users_group])
end
def destroy
......
......@@ -15,62 +15,10 @@ module CommitsHelper
commit_person_link(commit, options.merge(source: :committer))
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)
diff_arr = diff.diff.lines.to_a
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)
Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old|
yield(full_line, type, line_code, line_new, line_old)
end
if line[0] == "+"
line_new += 1
elsif line[0] == "-"
line_old += 1
else
line_new += 1
line_old += 1
end
end
end
def each_diff_line_near(diff, index, expected_line_code)
......
module DashboardHelper
def dashboard_filter_path(entity, options={})
def filter_path(entity, options={})
exist_opts = {
status: params[:status],
project_id: params[:project_id],
......@@ -7,12 +7,9 @@ module DashboardHelper
options = exist_opts.merge(options)
case entity
when 'issue' then
issues_dashboard_path(options)
when 'merge_request'
merge_requests_dashboard_path(options)
end
path = request.path
path << "?#{options.to_param}"
path
end
def entities_per_project project, entity
......
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)
"You are going to remove #{user.name} from #{group.name} Group. Are you sure?"
end
......
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
......@@ -39,12 +39,12 @@ module TreeHelper
#
# Returns boolean
def markup?(filename)
filename.end_with?(*%w(.textile .rdoc .org .creole
filename.downcase.end_with?(*%w(.textile .rdoc .org .creole
.mediawiki .rst .asciidoc .pod))
end
def gitlab_markdown?(filename)
filename.end_with?(*%w(.mdown .md .markdown))
filename.downcase.end_with?(*%w(.mdown .md .markdown))
end
def plain_text_readme? filename
......@@ -57,6 +57,8 @@ module TreeHelper
end
def allowed_tree_edit?
return false unless @repository.branch_names.include?(@ref)
if @project.protected_branch? @ref
can?(current_user, :push_code_to_protected_branches, @project)
else
......
# Will be removed in 6.1 with tables
#
# == Schema Information
#
# Table name: user_teams
......
# Will be removed in 6.1 with tables
#
# == Schema Information
#
# Table name: user_team_project_relationships
......
# Will be removed in 6.1 with tables
#
# == Schema Information
#
# Table name: user_team_user_relationships
......
......@@ -149,11 +149,12 @@ class MergeRequest < ActiveRecord::Base
end
def unmerged_diffs
if for_fork?
diffs = Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
diffs = if for_fork?
Gitlab::Satellite::MergeAction.new(author, self).diffs_between_satellite
else
diffs = target_project.repository.diffs_between(source_branch, target_branch)
Gitlab::Git::Diff.between(project.repository, source_branch, target_branch)
end
diffs ||= []
diffs
end
......
......@@ -50,6 +50,9 @@ class Note < ActiveRecord::Base
scope :inc_author_project, ->{ includes(:project, :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)
create({
noteable: noteable,
......@@ -67,14 +70,31 @@ class Note < ActiveRecord::Base
nil
end
def diff
if noteable.diffs.present?
noteable.diffs.select do |d|
if d.new_path
Digest::SHA1.hexdigest(d.new_path) == diff_file_index
def find_diff
return nil unless noteable && noteable.diffs.present?
@diff ||= noteable.diffs.find do |d|
Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path
end
end.first
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
def diff_file_index
......@@ -82,13 +102,29 @@ class Note < ActiveRecord::Base
end
def diff_file_name
diff.new_path
diff.new_path if diff
end
def diff_old_line
line_code.split('_')[1].to_i
end
def diff_new_line
line_code.split('_')[2].to_i
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
@discussion_id ||= [:discussion, noteable_type.try(:underscore), noteable_id || commit_id, line_code].join("-").to_sym
end
......
......@@ -18,19 +18,25 @@ class Repository
end
def commit(id = nil)
commit = raw_repository.commit(id)
commit = Gitlab::Git::Commit.find(raw_repository, id)
commit = Commit.new(commit) if commit
commit
end
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
end
def commits_between(target, source)
commits = raw_repository.commits_between(target, source)
def commits_between(from, to)
commits = Gitlab::Git::Commit.between(raw_repository, from, to)
commits = Commit.decorate(commits) if commits.present?
commits
end
......@@ -43,6 +49,12 @@ class Repository
tags.find { |tag| tag.name == name }
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)
Rails.cache.delete(cache_key(:branch_names))
......
......@@ -102,19 +102,22 @@ class NotificationService
# ignore wall messages
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 }
if note.commit_id.present?
opts.merge!(commit_id: note.commit_id)
recipients = [note.commit_author]
else
opts.merge!(noteable_id: note.noteable_id)
end
target = note.noteable
if target.respond_to?(:participants)
recipients = target.participants
else
recipients = []
end
recipients = note.mentioned_users
end
# Get users who left comment in thread
......
......@@ -4,22 +4,22 @@
- if @group.errors.any?
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix.group_name_holder
.control-group.group_name_holder
= f.label :name do
Group name is
.input
= f.text_field :name, placeholder: "Example Group", class: "xxlarge"
.controls
= f.text_field :name, placeholder: "Example Group", class: "input-xxlarge"
.clearfix.group-description-holder
.control-group.group-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.controls
= 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
%span.cred Group path is
.input
= f.text_field :path, placeholder: "example-group", class: "xxlarge danger"
.controls
= f.text_field :path, placeholder: "example-group", class: "input-xxlarge danger"
%ul.cred
%li Changing group path can have unintended side effects.
%li Renaming group path will rename directory for all related projects
......
......@@ -4,7 +4,7 @@
allows you to keep projects organized.
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
= form_tag admin_groups_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "span6"
......
......@@ -4,15 +4,15 @@
- if @group.errors.any?
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
.control-group
= f.label :name do
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
.clearfix.group-description-holder
.controls
= f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
.control-group.group-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.controls
= f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
.form-actions
= f.submit 'Create group', class: "btn btn-create"
......
......@@ -10,10 +10,10 @@
.alert.alert-error
- @hook.errors.full_messages.each do |msg|
%p= msg
.clearfix
.control-group
= f.label :url, "URL:"
.input
= f.text_field :url, class: "text_field xxlarge"
.controls
= f.text_field :url, class: "text_field input-xxlarge input-xpadding"
&nbsp;
= f.submit "Add System Hook", class: "btn btn-create"
%hr
......
......@@ -38,7 +38,7 @@
.title
Projects (#{@projects.total_count})
.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
- @projects.each do |project|
%li
......
......@@ -8,28 +8,28 @@
%fieldset
%legend Account
.clearfix
.control-group
= f.label :name
.input
.controls
= f.text_field :name, required: true, autocomplete: "off"
%span.help-inline * required
.clearfix
.control-group
= f.label :username
.input
.controls
= f.text_field :username, required: true, autocomplete: "off"
%span.help-inline * required
.clearfix
.control-group
= f.label :email
.input
.controls
= f.text_field :email, required: true, autocomplete: "off"
%span.help-inline * required
- if @user.new_record?
%fieldset
%legend Password
.clearfix
.control-group
= f.label :password
.input
.controls
%strong
A temporary password will be generated and sent to user.
%br
......@@ -37,33 +37,33 @@
- else
%fieldset
%legend Password
.clearfix
.control-group
= f.label :password
.input= f.password_field :password, disabled: f.object.force_random_password
.clearfix
.controls= f.password_field :password, disabled: f.object.force_random_password
.control-group
= 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
%legend Access
.row
.span8
.clearfix
.control-group
= f.label :projects_limit
.input= f.number_field :projects_limit
.controls= f.number_field :projects_limit
.clearfix
.control-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
.input= f.check_box :can_create_team
.controls= f.check_box :can_create_team
.clearfix
.control-group
= f.label :admin do
%strong.cred Administrator
.input= f.check_box :admin
.controls= f.check_box :admin
.span4
- unless @user.new_record?
.alert.alert-error
......@@ -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"
%fieldset
%legend Profile
.clearfix
.control-group
= f.label :skype
.input= f.text_field :skype
.clearfix
.controls= f.text_field :skype
.control-group
= f.label :linkedin
.input= f.text_field :linkedin
.clearfix
.controls= f.text_field :linkedin
.control-group
= f.label :twitter
.input= f.text_field :twitter
.controls= f.text_field :twitter
.actions
.form-actions
- if @user.new_record?
= f.submit 'Create user', class: "btn btn-create"
= link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
......
......@@ -30,7 +30,7 @@
.title
Users (#{@users.total_count})
.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
- @users.each do |user|
%li
......
%h3.page-title
Issues
%span.light
&ndash;
Assigned to you
Issues assigned to me
%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
.span3
= render 'filter', entity: 'issue'
= render 'shared/filter', entity: 'issue'
.span9
- if @issues.any?
- @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
= render 'shared/issues'
%h3.page-title
Merge Requests
%span.light
&ndash;
Authored by or assigned to you
%span.pull-right #{@merge_requests.total_count} merge requests
%p.light
Only merge requests authored or assigned to you are listed here.
%hr
.row
.span3
= render 'filter', entity: 'merge_request'
= render 'shared/filter', entity: 'merge_request'
.span9
= 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
.span3
%ul.nav.nav-pills.nav-stacked
......@@ -32,7 +36,7 @@
= label.name
.span9
%ul.bordered-list.my-projects
%ul.bordered-list.my-projects.top-list
- @projects.each do |project|
%li
%h4.project-title
......
= form_for @users_group, url: group_users_groups_path(@group) do |f|
%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
.clearfix
%p 1. Choose users you want in the group
.control-group
= 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
.clearfix
%p 2. Set access level for them
.control-group
= 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
= f.submit 'Add users into group', class: "btn btn-create"
......
......@@ -20,22 +20,22 @@
.ui-box
.title
%strong= @group.name
Group Settings:
group settings:
%div.form-holder
= form_for @group do |f|
- if @group.errors.any?
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
.control-group
= f.label :name do
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
.controls
= f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
.clearfix.group-description-holder
.control-group.group-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.controls
= f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
.form-actions
= f.submit 'Save group', class: "btn btn-save"
......@@ -44,7 +44,7 @@
.ui-box
.title
%strong= @group.name
Projects:
projects:
- if can? current_user, :manage_group, @group
%span.pull-right
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-tiny" do
......@@ -85,4 +85,4 @@
%p
%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 @@
%hr
.row
.span3
= render 'filter', entity: 'issue'
= render 'shared/filter', entity: 'issue'
.span9
- if @issues.any?
- @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
= render 'shared/issues'
%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
.row
.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
.ui-box
.title
%strong #{@group.name}
Group Members
group members
%small
(#{@members.count})
%ul.well-list
- @members.each do |member|
= render 'users_groups/users_group', member: member, show_controls: can_manage_group
%p.light
Group members get access to all projects in this group
- if can_manage_group
= render "new_group_member"
......@@ -6,6 +6,6 @@
%hr
.row
.span3
= render 'filter', entity: 'merge_request'
= render 'shared/filter', entity: 'merge_request'
.span9
= render 'shared/merge_requests'
......@@ -2,19 +2,19 @@
- if @group.errors.any?
.alert.alert-error
%span= @group.errors.full_messages.first
.clearfix
.control-group
= f.label :name do
Group name is
.input
= f.text_field :name, placeholder: "Ex. OpenSource", class: "xxlarge left"
.controls
= f.text_field :name, placeholder: "Ex. OpenSource", class: "input-xxlarge left"
.clearfix.group-description-holder
.control-group.group-description-holder
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 250, class: "xxlarge js-gfm-input", rows: 4
.controls
= f.text_area :description, maxlength: 250, class: "input-xxlarge js-gfm-input", rows: 4
.clearfix
.input
.control-group
.controls
%ul
%li Group is kind of directory for several projects
%li All created groups are private
......
......@@ -8,8 +8,6 @@
%br
Fast, secure and stable solution based on Ruby on Rails.
%br
.row
.span4
.ui-box
......
......@@ -4,7 +4,7 @@
- if Gitlab.config.gitlab.signup_enabled
Your account has been created successfully.
- 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
login..........................................
%code= @user['email']
......
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 %>
<% 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?
- if Gitlab.config.omniauth.enabled
%fieldset
......@@ -20,15 +27,15 @@
- @user.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :password
.input= f.password_field :password, required: true
.clearfix
.controls= f.password_field :password, required: true
.control-group
= f.label :password_confirmation
.input
.controls
= f.password_field :password_confirmation, required: true
.clearfix
.input
.control-group
.controls
= f.submit 'Save password', class: "btn btn-save"
......@@ -47,7 +54,7 @@
It can be used for atom feed or API
%p.cgray
- 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"
- else
%span You don`t have one yet. Click generate to fix it.
......@@ -63,7 +70,7 @@
= form_for @user, url: update_username_profile_path, method: :put, remote: true do |f|
.padded
= f.label :username
.input
.controls
= f.text_field :username, required: true
&nbsp;
%span.loading-gif.hide= image_tag "ajax_loader.gif"
......@@ -76,7 +83,7 @@
%ul.cred
%li It will change web url 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"
- 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|
%fieldset.application-theme
%legend
......
.ui-box
.title
%strong Groups
(#{@groups.count})
%h3.page-title
Group membership
- if current_user.can_create_group?
%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
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
- @groups.each do |group|
- @user_groups.each do |user_group|
- group = user_group.group
%li
.pull-right
- if can?(current_user, :manage_group, group)
......@@ -23,4 +29,7 @@
= link_to group, class: 'group-name' do
= 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
= render @events
%hr
......
......@@ -6,18 +6,18 @@
- @key.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :title
.input= f.text_field :title
.clearfix
.controls= f.text_field :title, class: "input-xlarge"
.control-group
= f.label :key
.input
.controls
%p.light
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"
= 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
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
= link_to "generate it", help_ssh_path
%hr
.ui-box
.title
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
= render @keys
- if @keys.blank?
......
......@@ -2,6 +2,8 @@
.row
.span4
%span
= notification_icon(notification)
- if membership.kind_of? UsersGroup
= link_to membership.group.name, membership.group
- else
......
%h3.page-title Setup your notification level
%h3.page-title
Notifications settings
%p.light
Application use email specified in your profile for notifications
%hr
.alert.alert-info
%p
%i.icon-circle.cred
%strong Disabled
&ndash; You will not get any notifications via email
%p.light
%p
%i.icon-circle.cblue
%strong Participating
&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
&ndash; You will receive all notifications from projects in which you participate
%hr
.row
.span4
%h5 Global setting
%h4
= notification_icon(@notification)
Global setting
.span7
= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
= hidden_field_tag :notification_type, 'global'
......@@ -30,20 +38,21 @@
= radio_button_tag :notification_level, Notification::N_WATCH, @notification.watch?, class: 'trigger-submit'
%span Watch
%hr
%br
= link_to '#', class: 'js-toggle-visibility-link' do
%h6.btn.btn-tiny
%span.btn.btn-tiny
%i.icon-chevron-down
%span Advanced notifications settings
.js-toggle-visibility-container.hide
%h5 Groups:
%ul.well-list
%hr
%h4 Groups:
%ul.bordered-list
- @users_groups.each do |users_group|
- notification = Notification.new(users_group)
= render 'settings', type: 'group', membership: users_group, notification: notification
%h5 Projects:
%ul.well-list
%h4 Projects:
%ul.bordered-list
- @users_projects.each do |users_project|
- notification = Notification.new(users_project)
= render 'settings', type: 'project', membership: users_project, notification: notification
......
......@@ -10,13 +10,13 @@
- @user.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :password
.input= f.password_field :password, required: true
.clearfix
.controls= f.password_field :password, required: true
.control-group
= f.label :password_confirmation
.input
.controls
= f.password_field :password_confirmation, required: true
.clearfix
.input
.control-group
.controls
= f.submit 'Set new password', class: "btn btn-create"
......@@ -87,4 +87,4 @@
= link_to "Add Public Key", new_profile_key_path, class: "btn btn-small"
.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
%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-title
%i.icon-file
%span.file_name
= @blob.name
= @path
%small= number_to_human_size @blob.size
%span.options= render "projects/blob/actions"
.file-content.blame
......
.btn-group.tree-btn-group
-# only show edit link for text files
- if @blob.text?
= link_to "edit", project_edit_tree_path(@project, @id), class: "btn btn-tiny", disabled: !allowed_tree_edit?
= link_to "raw", project_raw_path(@project, @id), class: "btn btn-tiny", target: "_blank"
= 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-small", target: "_blank"
-# only show normal/blame view links for text files
- if @blob.text?
- 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
= link_to "blame", project_blame_path(@project, @id), class: "btn btn-tiny" unless @blob.empty?
= link_to "history", project_commits_path(@project, @id), class: "btn btn-tiny"
= 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-small"
%ul.nav.nav-pills.nav-stacked
= nav_link(path: 'repositories#show') do
= link_to 'Recent', project_repository_path(@project)
= nav_link(path: 'branches#recent') do
= link_to 'Recent', recent_project_branches_path(@project)
= nav_link(path: 'protected_branches#index') do
= link_to project_protected_branches_path(@project) do
Protected
......
= render "projects/commits/head"
.row
.span3
= render "projects/repositories/filter"
= render "filter"
.span9
- unless @branches.empty?
%ul.bordered-list
......
......@@ -4,6 +4,5 @@
= render "filter"
.span9
%ul.bordered-list
- @activities.each do |update|
= render "projects/branches/branch", branch: update.head
- @branches.each do |branch|
= render "projects/branches/branch", branch: branch
......@@ -7,7 +7,7 @@
= link_to 'Compare', project_compare_index_path(@project)
= 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
%span.badge= @repository.branches.length
......
......@@ -3,7 +3,7 @@
%a.supp_diff_link Diff suppressed. Click to show
%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}" }
- if type == "match"
%td.old_line= "..."
......@@ -20,4 +20,4 @@
- if @reply_allowed
- comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
- 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"
- if @path.present?
%ul.breadcrumb
%ul.breadcrumb.commit-breadcrumb
%li.light
History for
= commits_breadcrumbs
......
......@@ -14,9 +14,9 @@
.pull-left
- 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'}
= 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
&nbsp;
= submit_tag "Compare", class: "btn btn-create commits-compare-btn"
......
......@@ -4,5 +4,6 @@
- else
:plain
$(".project-edit-errors").html("#{escape_javascript(render('errors'))}");
$('.project-submit').enable();
$('.save-project-loader').hide();
$('.project-edit-container').show();
......@@ -6,18 +6,18 @@
- @key.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :title
.input= f.text_field :title
.clearfix
.controls= f.text_field :title, class: 'input-xlarge'
.control-group
= f.label :key
.input
= f.text_area :key, class: [:xxlarge, :thin_area]
%p.hint
.controls
%p.light
Paste a machine public key here. Read more about how generate it
= 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"
= link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
%p.slead
Deploy keys allow read-only access to repository. They can be used for CI, staging or production servers
%h3.page-title
Deploy keys allow read-only access to repository
%p
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
= link_to new_project_deploy_key_path(@project), class: "btn btn-new pull-right", title: "New Deploy Key" do
%i.icon-plus
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
.row
.span5.enabled-keys
%h5.cgreen
Enabled deploy keys
%small for this project
%h5
%strong.cgreen Enabled deploy keys
for this project
%ul.bordered-list
= render @enabled_keys
- if @enabled_keys.blank?
......@@ -21,10 +23,10 @@
%p.nothing_here_message Create #{link_to 'new deploy key', new_project_deploy_key_path(@project)} or add existing one
.span5.available-keys
%h5
Available deploy keys
%small from projects you are able to manage
%strong Deploy keys
from projects available for you
%ul.bordered-list
= render @available_keys
- if @available_keys.blank?
.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 @@
.ui-box.white
.title
%strong= @project.name
Project Settings:
project settings:
.form-holder
= form_for(@project, remote: true) do |f|
%fieldset
.clearfix.project_name_holder
.control-group.project_name_holder
= f.label :name do
Project name is
.input
.controls
= f.text_field :name, placeholder: "Example Project", class: "span5"
.clearfix
.control-group
= f.label :description do
Project description
%span.light (optional)
.input
.controls
= f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250
- unless @project.empty_repo?
.clearfix
- if @project.repository.exists? && @project.repository.branch_names.any?
.control-group
= 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)
......@@ -66,11 +66,11 @@
- if Project.issues_tracker.values.count > 1
.control-group
= 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'
.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
= f.label :merge_requests_enabled, "Merge Requests", class: 'control-label'
......@@ -98,7 +98,7 @@
.form-actions
= f.submit 'Save', class: "btn btn-save"
= f.submit 'Save changes', class: "btn btn-save"
- if can?(current_user, :change_namespace, @project)
.ui-box.ui-box-danger
......@@ -110,7 +110,7 @@
= f.label :namespace_id do
%span Namespace
.controls
.clearfix
.control-group
= f.select :namespace_id, namespaces_options(@project.namespace_id), {prompt: 'Choose a project namespace'}, {class: 'chosen'}
%ul
%li Be careful. Changing project namespace can have unintended side effects
......@@ -130,7 +130,7 @@
= f.label :path do
%span Path
.controls
.clearfix
.control-group
= f.text_field :path
%ul
%li Be careful. Rename of project repo can have unintended side effects
......
%h3.page-title Edit mode
.file-editor
= form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
.file-holder
......
......@@ -11,10 +11,10 @@
.alert.alert-error
- @hook.errors.full_messages.each do |msg|
%p= msg
.clearfix
.control-group
= f.label :url, "URL:"
.input
= f.text_field :url, class: "text_field xxlarge"
.controls
= f.text_field :url, class: "text_field input-xxlarge input-xpadding", placeholder: 'http://example.com/trigger-ci.json'
&nbsp;
= f.submit "Add Web Hook", class: "btn btn-create"
%hr
......
......@@ -18,6 +18,9 @@
All
%fieldset
%hr
= link_to "Reset", project_issues_path(@project), class: 'btn pull-right'
- if %w(status milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
= link_to project_issues_path(@project), class: 'cgray pull-right' do
%i.icon-remove
Clear filter
......@@ -8,18 +8,18 @@
%br
.ui-box.ui-box-show
.ui-box-head
.clearfix
.control-group
= f.label :title do
%strong= "Subject *"
.input
= f.text_field :title, maxlength: 255, class: "xxlarge js-gfm-input", autofocus: true, required: true
.controls
= f.text_field :title, maxlength: 255, class: "input-xxlarge js-gfm-input", autofocus: true, required: true
.ui-box-body
.clearfix
.control-group
.issue_assignee.pull-left
= f.label :assignee_id do
%i.icon-user
Assign to
.input
.controls
.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'})
.pull-right
......@@ -29,25 +29,25 @@
= f.label :milestone_id do
%i.icon-time
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
.clearfix
.control-group
= f.label :label_list do
%i.icon-tag
Labels
.input
= f.text_field :label_list, maxlength: 2000, class: "xxlarge"
.controls
= f.text_field :label_list, maxlength: 2000, class: "input-xxlarge"
%p.hint Separate labels with commas.
.clearfix
.control-group
= f.label :description, "Details"
.input
= f.text_area :description, class: "xxlarge js-gfm-input", rows: 14
.controls
= 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'}.
.actions
.form-actions
- if @issue.new_record?
= f.submit 'Submit new issue', class: "btn btn-create"
-else
......
......@@ -6,7 +6,7 @@
.pull-right
.span6
- 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
New Issue
= form_tag project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: 'pull-right' do
......@@ -14,7 +14,7 @@
= 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 :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
.span3
......
= form_tag project_issues_path(@project), method: 'get' do
%fieldset
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
= link_to project_merge_requests_path(@project, f: 'open', milestone_id: params[:milestone_id]) do
%li{class: ("active" if (params[:status] == 'open' || !params[:status]))}
= link_to project_merge_requests_path(@project, status: 'open', milestone_id: params[:milestone_id]) do
Open
%li{class: ("active" if params[:f] == "closed")}
= link_to project_merge_requests_path(@project, f: "closed", milestone_id: params[:milestone_id]) do
%li{class: ("active" if params[:status] == "closed")}
= link_to project_merge_requests_path(@project, status: "closed", milestone_id: params[:milestone_id]) do
Closed
%li{class: ("active" if params[:f] == 'assigned-to-me')}
= link_to project_merge_requests_path(@project, f: 'assigned-to-me', milestone_id: params[:milestone_id]) do
%li{class: ("active" if params[:status] == 'assigned-to-me')}
= link_to project_merge_requests_path(@project, status: 'assigned-to-me', milestone_id: params[:milestone_id]) do
Assigned To Me
%li{class: ("active" if params[:f] == 'all')}
= link_to project_merge_requests_path(@project, f: 'all', milestone_id: params[:milestone_id]) do
%li{class: ("active" if params[:status] == 'all')}
= link_to project_merge_requests_path(@project, status: 'all', milestone_id: params[:milestone_id]) do
All
%fieldset
%hr
= link_to "Reset", project_merge_requests_path(@project), class: 'btn pull-right'
- if %w(status milestone_id assignee_id label_name).select { |k| params[k].present? }.any?
= link_to project_merge_requests_path(@project), class: 'cgray pull-right' do
%i.icon-remove
Clear filter
......@@ -33,21 +33,21 @@
%i.icon-paper-clip
Details
.merge-request-form-info
.clearfix
.control-group
= f.label :title do
%strong= "Title *"
.input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true
.clearfix
.controls= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5, required: true
.control-group
.left
= f.label :assignee_id do
%i.icon-user
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
= f.label :milestone_id do
%i.icon-time
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
- if @merge_request.new_record?
......
%h3.page-title
= "Edit merge request #{@merge_request.id}"
= "Edit merge request ##{@merge_request.id}"
%hr
= render 'form'
- 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
New Merge Request
%h3.page-title
......
%div#modal_merge_info.modal.hide
.modal-header
%a.close{href: "#"} ×
%h3 How To Merge
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3 How to merge
.modal-body
- if @merge_request.for_fork?
- source_remote = @merge_request.source_project.namespace.nil? ? "source" :@merge_request.source_project.namespace.path
......
......@@ -11,7 +11,8 @@
%p
You can accept this request automatically.
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
.accept_group
= f.submit "Accept Merge Request", class: "btn btn-create accept_merge_request"
......@@ -31,7 +32,7 @@
.automerge_widget.cannot_be_merged{style: "display:none"}
.alert.alert-disabled
%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;
%strong This request can't be merged with GitLab. You should do it manually
......
......@@ -26,13 +26,13 @@
.span6
.control-group
= f.label :due_date, "Due Date", class: "control-label"
.input= f.hidden_field :due_date
.controls= f.hidden_field :due_date
.controls
.datepicker
.form-actions
- 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"
-else
= f.submit 'Save changes', class: "btn-save btn"
......
......@@ -4,8 +4,7 @@
= link_to edit_project_milestone_path(milestone.project, milestone), class: "btn btn-small edit-milestone-link grouped" do
%i.icon-edit
Edit
- if milestone.can_be_closed?
= link_to 'Close', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-remove"
= link_to 'Close Milestone', project_milestone_path(@project, milestone, milestone: {state_event: :close }), method: :put, remote: true, class: "btn btn-small btn-remove"
%h4
= link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
- if milestone.expired? and not milestone.closed?
......
......@@ -3,7 +3,7 @@
%h3.page-title
Milestones
- 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
New Milestone
......
= render "projects/issues/head"
.row
.span6
%h3.page-title
%h3.page-title
Milestone ##{@milestone.id}
%small
= @milestone.expires_at
.back-link
= link_to project_milestones_path(@project) do
&larr; To milestones list
.span6
.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)
= 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
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-head
......@@ -69,6 +60,11 @@
Participants
%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-pane.active#tab-issues
......
......@@ -15,7 +15,7 @@
.control-group
= label_tag :search , "Looking for commit:", class: 'control-label light'
.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
%i.icon-search
- @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
= render 'projects/errors'
.project-edit-content
= form_for @project, remote: true do |f|
.clearfix.project_name_holder
.control-group.project_name_holder
= f.label :name do
Project name is
.input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge", tabindex: 1, autofocus: true
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
%strong Project name is
.controls
= f.text_field :name, placeholder: "Example Project", class: "input-xlarge", tabindex: 1, autofocus: true
- if current_user.can_select_namespace?
.clearfix
.control-group
= f.label :namespace_id do
%span Namespace
.input
.controls
= f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen', tabindex: 2}
.clearfix
.input
.control-group
.controls
= link_to "#", class: 'appear-link' do
%i.icon-upload-alt
%span Import existing repository?
.clearfix.appear-data.import-url-data
.control-group.appear-data.import-url-data
= f.label :import_url do
%span Import existing repo
.input
= f.text_field :import_url, class: 'xlarge', placeholder: 'https://github.com/randx/six.git'
.controls
= f.text_field :import_url, class: 'input-xlarge', placeholder: 'https://github.com/randx/six.git'
.light
URL must be cloneable
.clearfix
.control-group
= f.label :description do
Description
%span.light (optional)
.input
= f.text_area :description, placeholder: "awesome project", class: "span5", rows: 3, maxlength: 250, tabindex: 3
.controls
= f.text_area :description, placeholder: "awesome project", class: "input-xlarge", rows: 3, maxlength: 250, tabindex: 3
%p.padded
New projects are private by default. You choose who can see the project and commit to repository.
%hr
.form-actions
= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4
- if current_user.can_create_group?
.clearfix
.input.light
.pull-right
.controls.light
Need a group for several dependent projects?
= link_to new_group_path, class: "btn btn-tiny" do
Create a group
......
- 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 }
%span.btn.disabled
%i.icon-comment
......
......@@ -36,7 +36,7 @@
ago
.discussion-body
- if note.for_diff_line?
- if note.diff
- if note.active?
.content
.file= render "projects/notes/discussion_diff", discussion_notes: discussion_notes, note: note
- else
......
......@@ -8,8 +8,11 @@
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
= link_to "#", title: "Edit comment", class: "js-note-edit" do
%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
%i.icon-trash.cred
Remove
= image_tag gravatar_icon(note.author_email), class: "avatar s32"
= link_to_member(@project, note.author, avatar: false)
%span.note-last-update
......
= render "projects/commits/head"
.row
.span3
= render "projects/repositories/filter"
= render "projects/branches/filter"
.span9
.alert.alert-info
%p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, class: "vlink"}.
......
......@@ -9,16 +9,16 @@
- @snippet.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :title
.input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.clearfix
.controls= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.control-group
= f.label "Lifetime"
.input= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
.clearfix
.controls= f.select :expires_at, lifetime_select_options, {}, {class: 'chosen span2'}
.control-group
.file-editor
= f.label :file_name, "File"
.input
.controls
.file-holder.snippet
.file-title
= f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true
......
......@@ -9,16 +9,16 @@
%li= msg
%h6 1. Choose people you want in the team
.clearfix
.control-group
= f.label :user_ids, "People"
.input
.controls
= users_select_tag(:user_ids, multiple: true)
%h6 2. Set access level for them
.clearfix
.control-group
= 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"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
.ui-box
.title
%strong #{@group.name} Group
members (#{@group.users_groups.count})
%strong #{@group.name}
group members (#{@group.users_groups.count})
.pull-right
= link_to members_group_path(@group), class: 'btn btn-small' do
%i.icon-edit
......
......@@ -2,8 +2,8 @@
- can_admin_project = (can? current_user, :admin_project, @project)
.ui-box
.title
%strong #{@project.name} Project
members (#{members.count})
%strong #{@project.name}
project members (#{members.count})
%ul.well-list
- members.each do |team_member|
= render 'team_member', member: team_member, current_user_can_admin_project: can_admin_project
%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
%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
%p.slead Choose project you want to use as team source:
.padded
= 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
= submit_tag 'Import', class: "btn btn-save"
.form-actions
= submit_tag 'Import project members', class: "btn btn-create"
= link_to "Cancel", project_team_index_path(@project), class: "btn btn-cancel"
......@@ -3,14 +3,14 @@
- if can? current_user, :admin_team_member, @project
%span.pull-right
= link_to import_project_team_members_path(@project), class: "btn btn-small grouped", title: "Import team from another project" 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
= link_to new_project_team_member_path(@project), class: "btn btn-new grouped", title: "New Team Member" do
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
Read more about project permissions
%strong= link_to "here", help_permissions_path, class: "vlink"
= render "team", members: @users_projects
- if @group
= render "group_members"
= render "team", members: @users_projects
......@@ -15,7 +15,7 @@
= 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;"
.ui-box-body
.input
.controls
%span.cgray
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
......@@ -23,14 +23,17 @@
\.
.ui-box-bottom
.control-group
= 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
.control-group
= f.label :commit_message
.input= f.text_field :message, class: 'span8'
.actions
= f.submit 'Save', class: "btn-save btn"
.controls= f.text_field :message, class: 'span8'
.form-actions
- if @wiki && @wiki.persisted?
= f.submit 'Save changes', class: "btn-save btn"
= link_to "Cancel", project_wiki_path(@project, @wiki), class: "btn btn-cancel"
- else
= f.submit 'Create page', class: "btn-create btn"
= link_to "Cancel", project_wiki_path(@project, :home), class: "btn btn-cancel"
......@@ -12,7 +12,7 @@
- if can?(current_user, :write_wiki, @project)
.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
New Page
......
%div#modal-new-wiki.modal.hide
.modal-header
%a.close{href: "#"} ×
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3.page-title New Wiki Page
.modal-body
= label_tag :new_wiki_path do
......
= render 'nav'
%h3.page-title
Git Access
Git access for
%strong= @gollum_wiki.path_with_namespace
= render 'main_links'
%br
.content
.project_clone_panel
.row
......
......@@ -7,7 +7,7 @@
.pull-right
= form_tag public_projects_path, method: :get, class: 'form-inline' do |f|
.search-holder
.input
.controls
= 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"
......
......@@ -2,7 +2,7 @@
.search-holder
= label_tag :search do
%span Looking for
.input
.controls
= 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 :group_id, params[:group_id]
......
= form_tag dashboard_filter_path(entity), method: 'get' do
= form_tag filter_path(entity), method: 'get' do
%fieldset
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if !params[:status])}
= link_to dashboard_filter_path(entity, status: nil) do
%li{class: ("active" if params[:status].blank?)}
= link_to filter_path(entity, status: nil) do
Open
%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
%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
%fieldset
%legend Projects:
%ul.nav.nav-pills.nav-stacked
%ul.nav.nav-pills.nav-pills-small.nav-stacked
- @projects.each do |project|
- unless entities_per_project(project, entity).zero?
%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
%small.pull-right= entities_per_project(project, entity)
%fieldset
%hr
= link_to "Reset", dashboard_filter_path(entity), class: 'btn pull-right'
- if params[:status].present? || params[:project_id].present?
= 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?
- @merge_requests.group_by(&:target_project).each do |group|
.ui-box
.ui-box.small-box
- project = group[0]
.title
= link_to_project project
%ul.well-list.mr-list
- group[1].each do |merge_request|
= render 'projects/merge_requests/merge_request', merge_request: merge_request
%hr
= paginate @merge_requests, theme: "gitlab"
- else
......
......@@ -9,16 +9,16 @@
- @snippet.errors.full_messages.each do |msg|
%li= msg
.clearfix
.control-group
= f.label :title
.input= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.clearfix
.controls= f.text_field :title, placeholder: "Example Snippet", class: 'input-xlarge', required: true
.control-group
= f.label "Private?"
.input= f.check_box :private, {class: ''}
.clearfix
.controls= f.check_box :private, {class: ''}
.control-group
.file-editor
= f.label :file_name, "File"
.input
.controls
.file-holder.snippet
.file-title
= f.text_field :file_name, placeholder: "example.rb", class: 'snippet-file-name', required: true
......
%h3.page-title
My Snippets
%small share code pastes with others out of git repository
.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
= link_to snippets_path, class: "btn btn-small grouped" do
= link_to snippets_path, class: "btn grouped" do
Discover snippets
%p.light
Share code pastes with others out of git repository
%hr
.row
......
%h3.page-title
Public snippets
%small share code pastes with others out of git repository
.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
= 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
%p.light
Public snippets created by you and other users are listed here
%hr
= render 'snippets'
......@@ -7,7 +7,7 @@
private
.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
......
- user = member.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"
%strong= user.name
%span.cgray= user.username
......@@ -8,12 +8,16 @@
%span.label.label-success It's you
%span.pull-right
- if @group.owners.include?(user)
%span.label.label-info Group Owner
- else
= member.human_access
%strong= member.human_access
- 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
%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
end
end
resources :branches, only: [:index, :new, :create, :destroy] do
collection do
get :recent
end
end
resources :tags, only: [:index, :new, :create, :destroy]
resources :branches, only: [:index, :new, :create, :destroy]
resources :protected_branches, only: [:index, :create, :destroy]
resources :refs, only: [] do
......
class AddStDiffToNote < ActiveRecord::Migration
def change
add_column :notes, :st_diff, :text, :null => true
end
end
......@@ -11,7 +11,7 @@
#
# 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|
t.integer "deploy_key_id", :null => false
......@@ -148,6 +148,7 @@ ActiveRecord::Schema.define(:version => 20130624162710) do
t.string "line_code"
t.string "commit_id"
t.integer "noteable_id"
t.text "st_diff"
end
add_index "notes", ["author_id"], :name => "index_notes_on_author_id"
......
......@@ -87,3 +87,4 @@ When listing resources you can pass the following parameters:
+ [php-gitlab-api](https://github.com/m4tthumphrey/php-gitlab-api) - PHP
+ [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.
# If you get a "command not found" error create a link to the python binary
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
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:
......@@ -119,7 +122,7 @@ GitLab Shell is a ssh access and repository management software developed specia
cd gitlab-shell
# 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
......@@ -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
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 core.autocrlf input
**Important Note:**
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
#### Teams
We drop teams support as separate entity for 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.
We deprecate teams as separate entity in 6.0 in favor of group membership.
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
......@@ -35,7 +39,14 @@ sudo -u git -H git fetch
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
cd /home/git/gitlab
......@@ -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_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_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/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
sudo rm /etc/init.d/gitlab
......@@ -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
```
### 6. Start application
### 7. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
### 8. Check application status
Check if GitLab and its environment are configured correctly:
......
......@@ -12,7 +12,7 @@ class Profile < Spinach::FeatureSteps
fill_in "user_skype", with: "testskype"
fill_in "user_linkedin", with: "testlinkedin"
fill_in "user_twitter", with: "testtwitter"
click_button "Save"
click_button "Save changes"
@user.reload
end
......
......@@ -7,7 +7,7 @@ class ProfileNotifications < Spinach::FeatureSteps
end
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"
end
end
......@@ -9,7 +9,7 @@ class ProjectFeature < Spinach::FeatureSteps
end
And 'I save project' do
click_button 'Save'
click_button 'Save changes'
end
Then 'I should see project with new settings' do
......
......@@ -5,7 +5,7 @@ class ProjectWiki < Spinach::FeatureSteps
include SharedPaths
Given 'I click on the Cancel button' do
within(:css, ".actions") do
within(:css, ".form-actions") do
click_on "Cancel"
end
end
......@@ -17,7 +17,7 @@ class ProjectWiki < Spinach::FeatureSteps
Given 'I create the Wiki Home page' do
fill_in "Content", with: '[link test](test)'
click_on "Save"
click_on "Create page"
end
Then 'I should see the newly created wiki page' do
......@@ -43,7 +43,7 @@ class ProjectWiki < Spinach::FeatureSteps
And 'I change the content' do
fill_in "Content", with: 'Updated Wiki Content'
click_on "Save"
click_on "Save changes"
end
Then 'I should see the updated content' do
......
module API
# Internal access API
class Internal < Grape::API
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack }
namespace 'internal' do
#
# Check if ssh key has access to project code
......@@ -26,16 +30,16 @@ module API
if key.is_a? DeployKey
key.projects.include?(project) && git_cmd == 'git-upload-pack'
key.projects.include?(project) && DOWNLOAD_COMMANDS.include?(git_cmd)
else
user = key.user
return false if user.blocked?
action = case git_cmd
when 'git-upload-pack', 'git-upload-archive'
when *DOWNLOAD_COMMANDS
then :download_code
when 'git-receive-pack'
when *PUSH_COMMANDS
then
if project.protected_branch?(params[:ref])
: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
# resolved (e.g., when a user inserts an invalid path or ref).
def assign_ref_vars
@id = get_id
@ref, @path = extract_ref(@id)
@repo = @project.repository
@commit = @repo.commit(@ref)
@tree = Tree.new(@repo, @commit.id, @ref, @path)
@hex_path = Digest::SHA1.hexdigest(@path)
@logs_path = logs_file_project_ref_path(@project, @ref, @path)
......
......@@ -3,7 +3,7 @@ module Gitlab
extend self
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
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
def reference_user(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
......
......@@ -49,7 +49,7 @@ module Gitlab
protected
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
end
end
......
......@@ -11,49 +11,10 @@ namespace :gitlab do
Rake::Task["gitlab:backup:repo:create"].invoke
Rake::Task["gitlab:backup:uploads:create"].invoke
# 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
# 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
backup = Backup::Manager.new
backup.pack
backup.cleanup
backup.remove_old
end
# Restore backup of GitLab system
......@@ -61,64 +22,15 @@ namespace :gitlab do
task restore: :environment do
warn_user_is_not_gitlab
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
backup = Backup::Manager.new
backup.unpack
Rake::Task["gitlab:backup:db:restore"].invoke
Rake::Task["gitlab:backup:repo:restore"].invoke
Rake::Task["gitlab:backup:uploads:restore"].invoke
Rake::Task["gitlab:shell:setup"].invoke
# 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
backup.cleanup
end
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"
task migrate_keys: :environment do
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
Key.find_each(batch_size: 20) do |key|
if key.valid? && key.save
print '.'
elsif key.fingerprint.present?
puts "\nDeleting #{key.inspect}".yellow
key.destroy
else
print 'F'
end
end
print "\n"
end
......@@ -3,7 +3,7 @@ require 'spec_helper'
describe Projects::CommitController do
let(:project) { create(:project_with_code) }
let(:user) { create(:user) }
let(:commit) { project.repository.last_commit_for("master") }
let(:commit) { project.repository.commit("master") }
before do
sign_in(user)
......
......@@ -175,8 +175,8 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository" do
subject { project_repository_path(project) }
describe "GET /project_code/branches/recent" do
subject { recent_project_branches_path(project) }
it { should be_allowed_for master }
it { should be_allowed_for reporter }
......@@ -186,7 +186,7 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository/branches" do
describe "GET /project_code/branches" do
subject { project_branches_path(project) }
before do
......@@ -202,7 +202,7 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository/tags" do
describe "GET /project_code/tags" do
subject { project_tags_path(project) }
before do
......@@ -417,8 +417,8 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository" do
subject { project_repository_path(project) }
describe "GET /project_code/branches/recent" do
subject { recent_project_branches_path(project) }
it { should be_allowed_for master }
it { should be_allowed_for reporter }
......@@ -428,7 +428,7 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository/branches" do
describe "GET /project_code/branches" do
subject { project_branches_path(project) }
before do
......@@ -444,7 +444,7 @@ describe "Application access" do
it { should be_denied_for :visitor }
end
describe "GET /project_code/repository/tags" do
describe "GET /project_code/tags" do
subject { project_tags_path(project) }
before do
......
......@@ -100,6 +100,32 @@ describe API::API do
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
def pull(key, project)
......@@ -121,4 +147,14 @@ describe API::API do
action: 'git-receive-pack'
)
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
......@@ -47,7 +47,7 @@ describe NotificationService do
end
context 'commit note' do
let(:note) { create :note_on_commit }
let(:note) { create(:note_on_commit) }
before do
build_team(note.project)
......@@ -55,32 +55,35 @@ describe NotificationService do
describe :new_note do
it do
should_email(@u_watcher.id)
should_not_email(note.author_id)
should_not_email(@u_participating.id)
should_not_email(@u_disabled.id)
should_email(@u_watcher.id, note)
should_not_email(@u_mentioned.id, note)
should_not_email(note.author_id, note)
should_not_email(@u_participating.id, note)
should_not_email(@u_disabled.id, note)
notification.new_note(note)
end
it do
create(:note_on_commit,
new_note = create(:note_on_commit,
author: @u_participating,
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_participating.id)
should_not_email(note.author_id)
should_not_email(@u_disabled.id)
notification.new_note(note)
should_email(@u_watcher.id, new_note)
should_email(@u_mentioned.id, new_note)
should_not_email(new_note.author_id, new_note)
should_not_email(@u_participating.id, new_note)
should_not_email(@u_disabled.id, new_note)
notification.new_note(new_note)
end
def should_email(user_id)
Notify.should_receive(:note_commit_email).with(user_id, note.id)
def should_email(user_id, n)
Notify.should_receive(:note_commit_email).with(user_id, n.id)
end
def should_not_email(user_id)
Notify.should_not_receive(:note_commit_email).with(user_id, note.id)
def should_not_email(user_id, n)
Notify.should_not_receive(:note_commit_email).with(user_id, n.id)
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