Merge branch 'master' into discussions
Conflicts: app/assets/stylesheets/main.scss app/models/project.rb app/views/notes/_common_form.html.haml app/views/notes/_per_line_form.html.haml lib/gitlab/markdown.rb spec/models/note_spec.rb
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
env:
 | 
			
		||||
  - DB=postgresql
 | 
			
		||||
  - DB=mysql
 | 
			
		||||
before_install:
 | 
			
		||||
  - sudo apt-get install libicu-dev -y
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +19,7 @@ services:
 | 
			
		|||
before_script:
 | 
			
		||||
  - "cp config/database.yml.$DB config/database.yml"
 | 
			
		||||
  - "cp config/gitlab.yml.example config/gitlab.yml"
 | 
			
		||||
  - "bundle exec rake db:create RAILS_ENV=test"
 | 
			
		||||
  - "bundle exec rake db:migrate RAILS_ENV=test"
 | 
			
		||||
  - "bundle exec rake db:setup RAILS_ENV=test"
 | 
			
		||||
  - "bundle exec rake db:seed_fu RAILS_ENV=test"
 | 
			
		||||
  - "sh -e /etc/init.d/xvfb start"
 | 
			
		||||
script: "bundle exec rake travis --trace"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								CHANGELOG
								
								
								
								
							
							
						
						| 
						 | 
				
			
			@ -1,4 +1,15 @@
 | 
			
		|||
v 4.0.0
 | 
			
		||||
  - Reorganized settings
 | 
			
		||||
  - Fixed commits compare
 | 
			
		||||
  - Refactored scss
 | 
			
		||||
  - Improve status checks
 | 
			
		||||
  - Validates presence of User#name
 | 
			
		||||
  - Fixed postgres support
 | 
			
		||||
  - Removed sqlite support
 | 
			
		||||
  - Modified post-receive hook
 | 
			
		||||
  - Milestones can be closed now
 | 
			
		||||
  - Show comment events on dashboard
 | 
			
		||||
  - Quick add team members via group#people page
 | 
			
		||||
  - [API] expose created date for hooks and SSH keys
 | 
			
		||||
  - [API] list, create issue notes
 | 
			
		||||
  - [API] list, create snippet notes
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,26 +1,26 @@
 | 
			
		|||
## Contribute to GitLab
 | 
			
		||||
# Contact & support
 | 
			
		||||
 | 
			
		||||
If you want to contribute to GitLab, follow this process:
 | 
			
		||||
If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq).
 | 
			
		||||
Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues.
 | 
			
		||||
 | 
			
		||||
1. Fork the project
 | 
			
		||||
2. Create a feature branch
 | 
			
		||||
3. Code
 | 
			
		||||
4. Create a pull request
 | 
			
		||||
 | 
			
		||||
We will only accept pull requests if:
 | 
			
		||||
 | 
			
		||||
* Your code has proper tests and all tests pass
 | 
			
		||||
* Your code can be merged w/o problems
 | 
			
		||||
* It won't break existing functionality
 | 
			
		||||
* It's quality code
 | 
			
		||||
* We like it :)
 | 
			
		||||
# Contribute to GitLab
 | 
			
		||||
 | 
			
		||||
For examples of feedback on pull requests please look at the [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
 | 
			
		||||
## Recipes
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
We collect user submitted installation scripts and config file templates for platforms we don't support officially.
 | 
			
		||||
We believe there is merit in allowing a certain amount of diversity.
 | 
			
		||||
You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc.
 | 
			
		||||
 | 
			
		||||
Install the Gitlab development in a virtual machine with the [Gitlab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm). Installing it in a virtual machine makes it much easier to set up all the dependencies for integration testing.
 | 
			
		||||
Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/)
 | 
			
		||||
 | 
			
		||||
## Running tests
 | 
			
		||||
 | 
			
		||||
For more information on running the tests please read the [development tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
 | 
			
		||||
## Feature suggestions
 | 
			
		||||
 | 
			
		||||
Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Code
 | 
			
		||||
 | 
			
		||||
Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								Gemfile
								
								
								
								
							
							
						
						| 
						 | 
				
			
			@ -32,7 +32,7 @@ gem 'grit_ext',      git: "https://github.com/gitlabhq/grit_ext.git",       ref:
 | 
			
		|||
gem "gitolite", '1.1.0'
 | 
			
		||||
 | 
			
		||||
# Syntax highlighter
 | 
			
		||||
gem "pygments.rb",  git: "https://github.com/gitlabhq/pygments.rb.git", ref: '4db80c599067e2d5f23c5c243bf85b8ca0368ad4'
 | 
			
		||||
gem "pygments.rb",  git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
 | 
			
		||||
 | 
			
		||||
# Language detection
 | 
			
		||||
gem "github-linguist", "~> 2.3.4" , require: "linguist"
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +100,7 @@ group :assets do
 | 
			
		|||
  gem "therubyracer"
 | 
			
		||||
 | 
			
		||||
  gem 'chosen-rails',     "0.9.8"
 | 
			
		||||
  gem 'jquery-atwho-rails', "0.1.6"
 | 
			
		||||
  gem 'jquery-atwho-rails', "0.1.7"
 | 
			
		||||
  gem "jquery-rails",     "2.1.3"
 | 
			
		||||
  gem "jquery-ui-rails",  "2.0.2"
 | 
			
		||||
  gem "modernizr",        "2.6.2"
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ group :development, :test do
 | 
			
		|||
  gem "capybara"
 | 
			
		||||
  gem "pry"
 | 
			
		||||
  gem "awesome_print"
 | 
			
		||||
  gem "database_cleaner"
 | 
			
		||||
  gem "database_cleaner", ref: "f89c34300e114be99532f14c115b2799a3380ac6", git: "https://github.com/bmabey/database_cleaner.git"
 | 
			
		||||
  gem "launchy"
 | 
			
		||||
  gem 'factory_girl_rails'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								Gemfile.lock
								
								
								
								
							
							
						
						| 
						 | 
				
			
			@ -1,3 +1,10 @@
 | 
			
		|||
GIT
 | 
			
		||||
  remote: https://github.com/bmabey/database_cleaner.git
 | 
			
		||||
  revision: f89c34300e114be99532f14c115b2799a3380ac6
 | 
			
		||||
  ref: f89c34300e114be99532f14c115b2799a3380ac6
 | 
			
		||||
  specs:
 | 
			
		||||
    database_cleaner (0.9.1)
 | 
			
		||||
 | 
			
		||||
GIT
 | 
			
		||||
  remote: https://github.com/ctran/annotate_models.git
 | 
			
		||||
  revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +52,8 @@ GIT
 | 
			
		|||
 | 
			
		||||
GIT
 | 
			
		||||
  remote: https://github.com/gitlabhq/pygments.rb.git
 | 
			
		||||
  revision: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
 | 
			
		||||
  ref: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
 | 
			
		||||
  revision: db1da0343adf86b49bdc3add04d02d2e80438d38
 | 
			
		||||
  branch: master
 | 
			
		||||
  specs:
 | 
			
		||||
    pygments.rb (0.3.2)
 | 
			
		||||
      posix-spawn (~> 0.3.6)
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +147,6 @@ GEM
 | 
			
		|||
    colorize (0.5.8)
 | 
			
		||||
    crack (0.3.1)
 | 
			
		||||
    daemons (1.1.9)
 | 
			
		||||
    database_cleaner (0.9.1)
 | 
			
		||||
    devise (2.1.2)
 | 
			
		||||
      bcrypt-ruby (~> 3.0)
 | 
			
		||||
      orm_adapter (~> 0.1)
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +233,7 @@ GEM
 | 
			
		|||
    httpauth (0.2.0)
 | 
			
		||||
    i18n (0.6.1)
 | 
			
		||||
    journey (1.0.4)
 | 
			
		||||
    jquery-atwho-rails (0.1.6)
 | 
			
		||||
    jquery-atwho-rails (0.1.7)
 | 
			
		||||
    jquery-rails (2.1.3)
 | 
			
		||||
      railties (>= 3.1.0, < 5.0)
 | 
			
		||||
      thor (~> 0.14)
 | 
			
		||||
| 
						 | 
				
			
			@ -458,7 +464,7 @@ DEPENDENCIES
 | 
			
		|||
  chosen-rails (= 0.9.8)
 | 
			
		||||
  coffee-rails (~> 3.2.2)
 | 
			
		||||
  colored
 | 
			
		||||
  database_cleaner
 | 
			
		||||
  database_cleaner!
 | 
			
		||||
  devise (~> 2.1.0)
 | 
			
		||||
  draper (~> 0.18.0)
 | 
			
		||||
  email_spec
 | 
			
		||||
| 
						 | 
				
			
			@ -481,7 +487,7 @@ DEPENDENCIES
 | 
			
		|||
  guard-spinach
 | 
			
		||||
  haml-rails (~> 0.3.5)
 | 
			
		||||
  httparty
 | 
			
		||||
  jquery-atwho-rails (= 0.1.6)
 | 
			
		||||
  jquery-atwho-rails (= 0.1.7)
 | 
			
		||||
  jquery-rails (= 2.1.3)
 | 
			
		||||
  jquery-ui-rails (= 2.0.2)
 | 
			
		||||
  kaminari (~> 0.14.1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
# Welcome to GitLab [](https://secure.travis-ci.org/gitlabhq/gitlabhq) [](https://secure.travis-ci.org/gitlabhq/grit) [](https://codeclimate.com/github/gitlabhq/gitlabhq)
 | 
			
		||||
# Welcome to GitLab [](https://travis-ci.org/gitlabhq/gitlabhq) [](https://travis-ci.org/gitlabhq/grit) [](https://codeclimate.com/github/gitlabhq/gitlabhq) [](https://gemnasium.com/gitlabhq/gitlabhq)
 | 
			
		||||
 | 
			
		||||
GitLab is a free project and repository management application
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 After Width: | Height: | Size: 8.2 KiB  | 
| 
		 Before Width: | Height: | Size: 2.9 KiB  | 
| 
		 Before Width: | Height: | Size: 3.2 KiB  | 
| 
		 Before Width: | Height: | Size: 4.5 KiB  | 
| 
		 Before Width: | Height: | Size: 3.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 2.1 KiB  | 
| 
		 Before Width: | Height: | Size: 2.3 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
						 | 
				
			
			@ -1,52 +1,38 @@
 | 
			
		|||
# Creates the variables for setting up GFM auto-completion
 | 
			
		||||
 | 
			
		||||
window.GitLab ?= {}
 | 
			
		||||
GitLab.GfmAutoComplete ?= {}
 | 
			
		||||
 | 
			
		||||
GitLab.GfmAutoComplete =
 | 
			
		||||
  # Emoji
 | 
			
		||||
data      = []
 | 
			
		||||
template  = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>"
 | 
			
		||||
GitLab.GfmAutoComplete.Emoji = {data, template}
 | 
			
		||||
  Emoji:
 | 
			
		||||
    data: []
 | 
			
		||||
    template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>'
 | 
			
		||||
 | 
			
		||||
  # Team Members
 | 
			
		||||
data      = []
 | 
			
		||||
url     = '';
 | 
			
		||||
params  = {private_token: '', page: 1}
 | 
			
		||||
GitLab.GfmAutoComplete.Members = {data, url, params}
 | 
			
		||||
  Members:
 | 
			
		||||
    data: []
 | 
			
		||||
    url: ''
 | 
			
		||||
    params:
 | 
			
		||||
      private_token: ''
 | 
			
		||||
    template: '<li data-value="${username}">${username} <small>${name}</small></li>'
 | 
			
		||||
 | 
			
		||||
  # Add GFM auto-completion to all input fields, that accept GFM input.
 | 
			
		||||
GitLab.GfmAutoComplete.setup = ->
 | 
			
		||||
  setup: ->
 | 
			
		||||
    input = $('.js-gfm-input')
 | 
			
		||||
 | 
			
		||||
    # Emoji
 | 
			
		||||
    input.atWho ':',
 | 
			
		||||
    data: GitLab.GfmAutoComplete.Emoji.data,
 | 
			
		||||
    tpl: GitLab.GfmAutoComplete.Emoji.template
 | 
			
		||||
      data: @Emoji.data
 | 
			
		||||
      tpl: @Emoji.template
 | 
			
		||||
 | 
			
		||||
    # Team Members
 | 
			
		||||
  input.atWho '@', (query, callback) ->
 | 
			
		||||
    (getMoreMembers = ->
 | 
			
		||||
      $.getJSON(GitLab.GfmAutoComplete.Members.url, GitLab.GfmAutoComplete.Members.params)
 | 
			
		||||
        .success (members) ->
 | 
			
		||||
          # pick the data we need
 | 
			
		||||
          newMembersData = $.map(members, (m) -> m.name )
 | 
			
		||||
 | 
			
		||||
          # add the new page of data to the rest
 | 
			
		||||
          $.merge(GitLab.GfmAutoComplete.Members.data, newMembersData)
 | 
			
		||||
 | 
			
		||||
          # show the pop-up with a copy of the current data
 | 
			
		||||
          callback(GitLab.GfmAutoComplete.Members.data[..])
 | 
			
		||||
 | 
			
		||||
          # are we past the last page?
 | 
			
		||||
          if newMembersData.length is 0
 | 
			
		||||
            # set static data and stop callbacks
 | 
			
		||||
    input.atWho '@',
 | 
			
		||||
              data: GitLab.GfmAutoComplete.Members.data
 | 
			
		||||
              callback: null
 | 
			
		||||
          else
 | 
			
		||||
            # get next page
 | 
			
		||||
            getMoreMembers()
 | 
			
		||||
      tpl: @Members.template
 | 
			
		||||
      callback: (query, callback) =>
 | 
			
		||||
        request_params = $.extend({}, @Members.params, query: query)
 | 
			
		||||
        $.getJSON(@Members.url, request_params).done (members) =>
 | 
			
		||||
          new_members_data = $.map(members, (m) ->
 | 
			
		||||
            username: m.username,
 | 
			
		||||
            name: m.name
 | 
			
		||||
          )
 | 
			
		||||
          callback(new_members_data)
 | 
			
		||||
 | 
			
		||||
      # so the next request gets the next page
 | 
			
		||||
      GitLab.GfmAutoComplete.Members.params.page += 1
 | 
			
		||||
    ).call()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,43 +1,3 @@
 | 
			
		|||
function switchToNewIssue(){
 | 
			
		||||
  $(".issues_content").hide("fade", { direction: "left" }, 150, function(){
 | 
			
		||||
    $('select#issue_assignee_id').chosen();
 | 
			
		||||
    $('select#issue_milestone_id').chosen();
 | 
			
		||||
    $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
 | 
			
		||||
    $('.top-tabs .add_new').hide();
 | 
			
		||||
    disableButtonIfEmptyField("#issue_title", ".save-btn");
 | 
			
		||||
    GitLab.GfmAutoComplete.setup();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function switchToEditIssue(){
 | 
			
		||||
  $(".issues_content").hide("fade", { direction: "left" }, 150, function(){
 | 
			
		||||
    $('select#issue_assignee_id').chosen();
 | 
			
		||||
    $('select#issue_milestone_id').chosen();
 | 
			
		||||
    $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
 | 
			
		||||
    $('.add_new').hide();
 | 
			
		||||
    disableButtonIfEmptyField("#issue_title", ".save-btn");
 | 
			
		||||
    GitLab.GfmAutoComplete.setup();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function switchFromNewIssue(){
 | 
			
		||||
  backToIssues();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function switchFromEditIssue(){
 | 
			
		||||
  backToIssues();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function backToIssues(){
 | 
			
		||||
  $("#edit_issue_dialog, #new_issue_dialog").hide("fade", { direction: "right" }, 150, function(){
 | 
			
		||||
    $(".issues_content").show("fade", { direction: "left" }, 150, function() { 
 | 
			
		||||
      $("#edit_issue_dialog").html("");
 | 
			
		||||
      $("#new_issue_dialog").html("");
 | 
			
		||||
      $('.add_new').show();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initIssuesSearch() { 
 | 
			
		||||
  var href       = $('#issue_search_form').attr('action');
 | 
			
		||||
  var last_terms = '';
 | 
			
		||||
| 
						 | 
				
			
			@ -76,23 +36,15 @@ function issuesPage(){
 | 
			
		|||
    $(this).closest("form").submit();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  $("#new_issue_link").click(function(){
 | 
			
		||||
    updateNewIssueURL();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  $('body').on('ajax:success', '.close_issue, .reopen_issue, #new_issue', function(){
 | 
			
		||||
  $('body').on('ajax:success', '.close_issue, .reopen_issue', function(){
 | 
			
		||||
    var t = $(this),
 | 
			
		||||
        totalIssues,
 | 
			
		||||
        reopen = t.hasClass('reopen_issue'),
 | 
			
		||||
        newIssue = false;
 | 
			
		||||
    if( this.id == 'new_issue' ){
 | 
			
		||||
      newIssue = true;
 | 
			
		||||
    }
 | 
			
		||||
    $('.issue_counter, #new_issue').each(function(){
 | 
			
		||||
        reopen = t.hasClass('reopen_issue');
 | 
			
		||||
    $('.issue_counter').each(function(){
 | 
			
		||||
      var issue = $(this);
 | 
			
		||||
      totalIssues = parseInt( $(this).html(), 10 );
 | 
			
		||||
 | 
			
		||||
      if( newIssue || ( reopen && issue.closest('.main_menu').length ) ){
 | 
			
		||||
      if( reopen && issue.closest('.main_menu').length ){
 | 
			
		||||
        $(this).html( totalIssues+1 );
 | 
			
		||||
      }else {
 | 
			
		||||
        $(this).html( totalIssues-1 );
 | 
			
		||||
| 
						 | 
				
			
			@ -126,20 +78,3 @@ function issuesCheckChanged() {
 | 
			
		|||
    $('.issues_filters').show();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateNewIssueURL(){
 | 
			
		||||
  var new_issue_link = $("#new_issue_link");
 | 
			
		||||
  var milestone_id = $("#milestone_id").val();
 | 
			
		||||
  var assignee_id = $("#assignee_id").val();
 | 
			
		||||
  var new_href = "";
 | 
			
		||||
  if(milestone_id){
 | 
			
		||||
    new_href = "issue[milestone_id]=" + milestone_id + "&";
 | 
			
		||||
  }
 | 
			
		||||
  if(assignee_id){
 | 
			
		||||
    new_href = new_href + "issue[assignee_id]=" + assignee_id;
 | 
			
		||||
  }
 | 
			
		||||
  if(new_href.length){
 | 
			
		||||
    new_href = new_issue_link.attr("href") + "?" + new_href;
 | 
			
		||||
    new_issue_link.attr("href", new_href);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,18 @@ window.slugify = (text) ->
 | 
			
		|||
window.ajaxGet = (url) ->
 | 
			
		||||
  $.ajax({type: "GET", url: url, dataType: "script"})
 | 
			
		||||
 | 
			
		||||
window.errorMessage = (message) ->
 | 
			
		||||
  ehtml = $("<p>")
 | 
			
		||||
  ehtml.addClass("error_message")
 | 
			
		||||
  ehtml.html(message)
 | 
			
		||||
  ehtml
 | 
			
		||||
 | 
			
		||||
window.split = (val) ->
 | 
			
		||||
  return val.split( /,\s*/ )
 | 
			
		||||
 | 
			
		||||
window.extractLast = (term) ->
 | 
			
		||||
  return split( term ).pop()
 | 
			
		||||
 | 
			
		||||
# Disable button if text field is empty
 | 
			
		||||
window.disableButtonIfEmptyField = (field_selector, button_selector) ->
 | 
			
		||||
  field = $(field_selector)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,12 @@ var MergeRequest = {
 | 
			
		|||
          self.showState(data.state);
 | 
			
		||||
        }, "json");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if(self.opts.ci_enable){
 | 
			
		||||
        $.get(self.opts.url_to_ci_check, function(data){
 | 
			
		||||
          self.showCiState(data.status);
 | 
			
		||||
        }, "json");
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  initTabs:
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +85,11 @@ var MergeRequest = {
 | 
			
		|||
      $(".automerge_widget." + state).show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  showCiState:
 | 
			
		||||
    function(state){
 | 
			
		||||
      $(".ci_widget").hide();
 | 
			
		||||
      $(".ci_widget.ci-" + state).show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  loadDiff:
 | 
			
		||||
    function() { 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,3 @@ $ ->
 | 
			
		|||
  # Ref switcher
 | 
			
		||||
  $('.project-refs-select').on 'change', ->
 | 
			
		||||
    $(@).parents('form').submit()
 | 
			
		||||
 | 
			
		||||
class @GraphNav
 | 
			
		||||
  @init: ->
 | 
			
		||||
    $('.graph svg').css 'position', 'relative'
 | 
			
		||||
    $('body').bind 'keyup', (e) ->
 | 
			
		||||
      $('.graph svg').animate(left: '+=400') if e.keyCode is 37 # left
 | 
			
		||||
      $('.graph svg').animate(left: '-=400') if e.keyCode is 39 # right
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 | 
			
		||||
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 | 
			
		||||
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 | 
			
		||||
 *= require jquery.ui.gitlab
 | 
			
		||||
 *= require jquery.atwho
 | 
			
		||||
 *= require chosen
 | 
			
		||||
 *= require_self
 | 
			
		||||
 *= require main
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
/*
 | 
			
		||||
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 | 
			
		||||
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 | 
			
		||||
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 | 
			
		||||
 *= require jquery.ui.gitlab
 | 
			
		||||
 *= require jquery.atwho
 | 
			
		||||
 *= require chosen
 | 
			
		||||
 *= require_self
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * GitLab bootstrap:
 | 
			
		||||
 */
 | 
			
		||||
@import "gitlab_bootstrap.scss";
 | 
			
		||||
 | 
			
		||||
@import "common.scss";
 | 
			
		||||
@import "ref_select.scss";
 | 
			
		||||
 | 
			
		||||
@import "sections/header.scss";
 | 
			
		||||
@import "sections/nav.scss";
 | 
			
		||||
@import "sections/commits.scss";
 | 
			
		||||
@import "sections/issues.scss";
 | 
			
		||||
@import "sections/projects.scss";
 | 
			
		||||
@import "sections/snippets.scss";
 | 
			
		||||
@import "sections/votes.scss";
 | 
			
		||||
@import "sections/merge_requests.scss";
 | 
			
		||||
@import "sections/graph.scss";
 | 
			
		||||
@import "sections/events.scss";
 | 
			
		||||
@import "sections/themes.scss";
 | 
			
		||||
@import "sections/tree.scss";
 | 
			
		||||
@import "sections/notes.scss";
 | 
			
		||||
@import "sections/profile.scss";
 | 
			
		||||
@import "sections/login.scss";
 | 
			
		||||
@import "sections/editor.scss";
 | 
			
		||||
 | 
			
		||||
@import "highlight/white.scss";
 | 
			
		||||
@import "highlight/dark.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * UI themes:
 | 
			
		||||
 */
 | 
			
		||||
@import "themes/ui_basic.scss";
 | 
			
		||||
@import "themes/ui_mars.scss";
 | 
			
		||||
@import "themes/ui_modern.scss";
 | 
			
		||||
@import "themes/ui_gray.scss";
 | 
			
		||||
@import "themes/ui_color.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Styles for JS behaviors.
 | 
			
		||||
 */
 | 
			
		||||
@import "behaviors.scss";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,20 +13,12 @@ body {
 | 
			
		|||
  margin: 0 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container  .sidebar {
 | 
			
		||||
  width: 200px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  min-height: 450px;
 | 
			
		||||
  float: right;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.visible_link,
 | 
			
		||||
.author_link {
 | 
			
		||||
  color: $link_color;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.help li { color:#111 }
 | 
			
		||||
.help li { color:$style_color; }
 | 
			
		||||
 | 
			
		||||
.back_link {
 | 
			
		||||
  text-decoration: underline;
 | 
			
		||||
| 
						 | 
				
			
			@ -65,6 +57,9 @@ table a code {
 | 
			
		|||
  background: url(ajax_loader.gif) no-repeat center center;
 | 
			
		||||
  width: 40px;
 | 
			
		||||
  height: 40px;
 | 
			
		||||
  &.loading-gray {
 | 
			
		||||
    background: url(ajax_loader_gray.gif) no-repeat center center;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** FLASH message **/
 | 
			
		||||
| 
						 | 
				
			
			@ -96,28 +91,17 @@ table a code {
 | 
			
		|||
  margin-right:50px
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.handle:hover {
 | 
			
		||||
  cursor: move;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
span.update-author {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
span.update-author {
 | 
			
		||||
  color: #999;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-style: italic;
 | 
			
		||||
}
 | 
			
		||||
span.update-author strong {
 | 
			
		||||
  strong {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    font-style: normal;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
/** UPDATE ITEM **/
 | 
			
		||||
span.update-author {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
/** END UPDATE ITEM **/
 | 
			
		||||
 | 
			
		||||
.dashboard-loader {
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin: 10px;
 | 
			
		||||
| 
						 | 
				
			
			@ -264,21 +248,6 @@ input.git_clone_url {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** bordered list **/
 | 
			
		||||
ul.bordered-list {
 | 
			
		||||
  margin: 5px 0px;
 | 
			
		||||
  padding: 0px;
 | 
			
		||||
  li {
 | 
			
		||||
    padding: 5px 0;
 | 
			
		||||
    border-bottom: 1px solid #EEE;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    display: block;
 | 
			
		||||
    margin: 0px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ul.bordered-list li:last-child { border:none }
 | 
			
		||||
 | 
			
		||||
.line_holder {
 | 
			
		||||
  &:hover {
 | 
			
		||||
    td {
 | 
			
		||||
| 
						 | 
				
			
			@ -316,98 +285,6 @@ p.time {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.ico {
 | 
			
		||||
  background: url("images.png") no-repeat -85px -77px;
 | 
			
		||||
  width: 19px;
 | 
			
		||||
  height: 16px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
  top: 8px;
 | 
			
		||||
 | 
			
		||||
  &.project {
 | 
			
		||||
    background-position:  -37px -77px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &.activities {
 | 
			
		||||
    background-position:-162px -22px;
 | 
			
		||||
  }
 | 
			
		||||
  &.projects {
 | 
			
		||||
    background-position:-209px -21px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.leftbar {
 | 
			
		||||
  h5, .title {
 | 
			
		||||
    padding: 5px 10px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  h4 {
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    padding: 2px 10px;
 | 
			
		||||
    color: #666;
 | 
			
		||||
    border-bottom: 1px solid #f1f1f1;
 | 
			
		||||
  }
 | 
			
		||||
  a:last-child h4 { border: none; }
 | 
			
		||||
 | 
			
		||||
  a:hover {
 | 
			
		||||
    h4 {
 | 
			
		||||
      color: #111;
 | 
			
		||||
      background: $hover;
 | 
			
		||||
      border-color: #CCC;
 | 
			
		||||
      .ico.project {
 | 
			
		||||
        background-position:-209px -21px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .bottom {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.votes {
 | 
			
		||||
  font-size: 13px;
 | 
			
		||||
  line-height: 15px;
 | 
			
		||||
  .progress {
 | 
			
		||||
    height: 4px;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    .bar {
 | 
			
		||||
      float: left;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
    }
 | 
			
		||||
    .bar-success {
 | 
			
		||||
      @include linear-gradient(#62C462, #51A351);
 | 
			
		||||
      background-color: #468847;
 | 
			
		||||
    }
 | 
			
		||||
    .bar-danger {
 | 
			
		||||
      @include linear-gradient(#EE5F5B, #BD362F);
 | 
			
		||||
      background-color: #B94A48;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .upvotes {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    color: #468847;
 | 
			
		||||
  }
 | 
			
		||||
  .downvotes {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    color: #B94A48;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.votes-block {
 | 
			
		||||
  margin: 14px 6px 6px 0;
 | 
			
		||||
  .downvotes {
 | 
			
		||||
    float: right;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.votes-inline {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  margin: 0 8px;
 | 
			
		||||
  .progress {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding: 0 0 2px;
 | 
			
		||||
    width: 45px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fix for readme code (stopped it from being yellow) */
 | 
			
		||||
.readme {
 | 
			
		||||
| 
						 | 
				
			
			@ -420,7 +297,6 @@ p.time {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.highlight_word {
 | 
			
		||||
  background: #EEDC94;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -428,23 +304,16 @@ p.time {
 | 
			
		|||
.status_info {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  padding: 5px 15px;
 | 
			
		||||
  line-height: 24px;
 | 
			
		||||
  width: 60px;
 | 
			
		||||
  line-height: 26px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin-right: 20px;
 | 
			
		||||
  float: right;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  top: -5px;
 | 
			
		||||
  @include border-radius(4px);
 | 
			
		||||
 | 
			
		||||
  &.success {
 | 
			
		||||
    background: #5BB75B;
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: 0 1px #111;
 | 
			
		||||
    border-color: #9A9;
 | 
			
		||||
  }
 | 
			
		||||
  &.error {
 | 
			
		||||
    background: #DA4E49;
 | 
			
		||||
    border-color: #BD362F;
 | 
			
		||||
    color: white;
 | 
			
		||||
    text-shadow: 0 1px #111;
 | 
			
		||||
    color: #FFF;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -463,16 +332,6 @@ p.time {
 | 
			
		|||
  height: 150px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.gitlab_pagination {
 | 
			
		||||
  span a { color: $link_color; }
 | 
			
		||||
  .prev, .next, .current, .page a {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
  }
 | 
			
		||||
  .current {
 | 
			
		||||
    border-bottom: 2px solid $style_color;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fixes alignment on notes.
 | 
			
		||||
.new_note {
 | 
			
		||||
  label {
 | 
			
		||||
| 
						 | 
				
			
			@ -647,10 +506,15 @@ pre {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.milestone .progress {
 | 
			
		||||
.milestone {
 | 
			
		||||
  &.milestone-closed {
 | 
			
		||||
    background: #eee;
 | 
			
		||||
  }
 | 
			
		||||
  .progress {
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
    margin-top: 4px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.float-link {
 | 
			
		||||
  float: left;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
/** Override bootstrap variables **/
 | 
			
		||||
$baseFontSize: 13px !default;
 | 
			
		||||
$baseLineHeight: 18px !default;
 | 
			
		||||
 | 
			
		||||
// BOOTSTRAP
 | 
			
		||||
@import "bootstrap";
 | 
			
		||||
@import "bootstrap/responsive-utilities";
 | 
			
		||||
@import "bootstrap/responsive-1200px-min";
 | 
			
		||||
 | 
			
		||||
@import "font-awesome";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * GitLab bootstrap.
 | 
			
		||||
 * Overrides some styles of twitter bootstrap.
 | 
			
		||||
 * Also give some common classes for GitLab app
 | 
			
		||||
 */
 | 
			
		||||
@import "gitlab_bootstrap/variables.scss";
 | 
			
		||||
@import "gitlab_bootstrap/fonts.scss";
 | 
			
		||||
@import "gitlab_bootstrap/mixins.scss";
 | 
			
		||||
@import "gitlab_bootstrap/common.scss";
 | 
			
		||||
@import "gitlab_bootstrap/typography.scss";
 | 
			
		||||
@import "gitlab_bootstrap/buttons.scss";
 | 
			
		||||
@import "gitlab_bootstrap/blocks.scss";
 | 
			
		||||
@import "gitlab_bootstrap/files.scss";
 | 
			
		||||
@import "gitlab_bootstrap/tables.scss";
 | 
			
		||||
@import "gitlab_bootstrap/lists.scss";
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
  .middle_box_content,
 | 
			
		||||
  .bottom_box_content {
 | 
			
		||||
    padding: 15px;
 | 
			
		||||
    word-wrap: break-word;
 | 
			
		||||
 | 
			
		||||
    pre {
 | 
			
		||||
      background: none !important;
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +41,15 @@
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .top_box_content {
 | 
			
		||||
    .box-title {
 | 
			
		||||
      color: $style_color;
 | 
			
		||||
      font-size: 18px;
 | 
			
		||||
      font-weight: normal;
 | 
			
		||||
      line-height: 28px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .middle_box_content {
 | 
			
		||||
    @include border-radius(0);
 | 
			
		||||
    border: none;
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +93,10 @@
 | 
			
		|||
    border-top: 1px solid #eaeaea;
 | 
			
		||||
    border-bottom: 1px solid #bbb;
 | 
			
		||||
 | 
			
		||||
    > a {
 | 
			
		||||
      text-shadow: 0 1px 1px #fff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.small {
 | 
			
		||||
      line-height: 28px;
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
| 
						 | 
				
			
			@ -138,19 +152,6 @@
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  li, .wll {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
    &:first-child {
 | 
			
		||||
      @include border-radius(4px 4px 0 0);
 | 
			
		||||
      border-top: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      @include border-radius(0 0 4px 4px);
 | 
			
		||||
      border: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .ui-box-body {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,11 +10,6 @@
 | 
			
		|||
/** COMMON CLASSES **/
 | 
			
		||||
.left { float:left }
 | 
			
		||||
.right { float:right!important }
 | 
			
		||||
.width-50p { width:50% }
 | 
			
		||||
.width-49p { width:49% }
 | 
			
		||||
.width-30p { width:30% }
 | 
			
		||||
.width-65p { width:65% }
 | 
			
		||||
.width-100p { width:100% }
 | 
			
		||||
.append-bottom-10 { margin-bottom:10px }
 | 
			
		||||
.append-bottom-20 { margin-bottom:20px }
 | 
			
		||||
.prepend-top-10 { margin-top:10px }
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +25,7 @@
 | 
			
		|||
.borders { border: 1px solid #ccc; @include shade; }
 | 
			
		||||
.hint { font-style: italic; color: #999; }
 | 
			
		||||
.light { color: #888 }
 | 
			
		||||
.tiny { font-weight: normal }
 | 
			
		||||
 | 
			
		||||
/** PILLS & TABS**/
 | 
			
		||||
.nav-pills a:hover { background-color: #888; }
 | 
			
		||||
| 
						 | 
				
			
			@ -99,18 +95,21 @@ input[type='search'].search-text-input {
 | 
			
		|||
  border: 1px solid #ccc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input[type='text'].danger {
 | 
			
		||||
  background: #F2DEDE!important;
 | 
			
		||||
  border-color: #D66;
 | 
			
		||||
  text-shadow: 0 1px 1px #fff
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fieldset legend { font-size: 17px; }
 | 
			
		||||
 | 
			
		||||
ul.nav.nav-projects-tabs {
 | 
			
		||||
  @extend .nav-tabs;
 | 
			
		||||
 | 
			
		||||
  padding-left: 8px;
 | 
			
		||||
 | 
			
		||||
  li {
 | 
			
		||||
    a {
 | 
			
		||||
      padding: 4px 20px;
 | 
			
		||||
      margin-top: 2px;
 | 
			
		||||
      border-color: #DDD;
 | 
			
		||||
    }
 | 
			
		||||
/** PAGINATION **/
 | 
			
		||||
.gitlab_pagination {
 | 
			
		||||
  span a { color: $link_color; }
 | 
			
		||||
  .prev, .next, .current, .page a {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
  }
 | 
			
		||||
  .current {
 | 
			
		||||
    border-bottom: 2px solid $style_color;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,11 +43,15 @@
 | 
			
		|||
        padding: 0 4px;
 | 
			
		||||
      }
 | 
			
		||||
      padding: 20px;
 | 
			
		||||
      h1, h2 {
 | 
			
		||||
        line-height: 46px;
 | 
			
		||||
      }
 | 
			
		||||
      h3, h4 {
 | 
			
		||||
        line-height: 40px;
 | 
			
		||||
 | 
			
		||||
      h1 { font-size: 26px; line-height: 46px; }
 | 
			
		||||
      h2 { font-size: 22px; line-height: 42px; }
 | 
			
		||||
      h3 { font-size: 20px; line-height: 40px; }
 | 
			
		||||
      h4 { font-size: 18px; line-height: 32px; }
 | 
			
		||||
      h5 { font-size: 16px; line-height: 26px; }
 | 
			
		||||
 | 
			
		||||
      .white .highlight pre {
 | 
			
		||||
        background: #f5f5f5;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,38 @@
 | 
			
		|||
/** LISTS **/
 | 
			
		||||
 | 
			
		||||
ul {
 | 
			
		||||
/**
 | 
			
		||||
   * List li block element #1
 | 
			
		||||
 * Well styled list
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
  .wll {
 | 
			
		||||
.well-list {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
  li {
 | 
			
		||||
    background-color: #FFF;
 | 
			
		||||
    padding: 10px 5px;
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
    min-height: 20px;
 | 
			
		||||
    border-bottom: 1px solid #eee;
 | 
			
		||||
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
 | 
			
		||||
 | 
			
		||||
    &.disabled {
 | 
			
		||||
      color: #888;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.smoke { background-color: #f5f5f5; }
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background: $hover;
 | 
			
		||||
      border-bottom: 1px solid #ADF;
 | 
			
		||||
    }
 | 
			
		||||
    &:last-child { border:none }
 | 
			
		||||
 | 
			
		||||
    &:first-child {
 | 
			
		||||
      @include border-radius(4px 4px 0 0);
 | 
			
		||||
      border-top: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      @include border-radius(0 0 4px 4px);
 | 
			
		||||
      border: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .author { color: #999; }
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +44,11 @@ ul {
 | 
			
		|||
        top: 3px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .well-title {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      line-height: 18px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,3 +59,17 @@ ol, ul {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** light list with border-bottom between li **/
 | 
			
		||||
ul.bordered-list {
 | 
			
		||||
  margin: 5px 0px;
 | 
			
		||||
  padding: 0px;
 | 
			
		||||
  li {
 | 
			
		||||
    padding: 5px 0;
 | 
			
		||||
    border-bottom: 1px solid #EEE;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    display: block;
 | 
			
		||||
    margin: 0px;
 | 
			
		||||
    &:last-child { border:none }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,3 +58,12 @@
 | 
			
		|||
@mixin solid-shade {
 | 
			
		||||
  @include box-shadow(0 0 0 3px #f1f1f1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin header-font {
 | 
			
		||||
  color: $style_color;
 | 
			
		||||
  text-shadow: 0 1px 1px #FFF;
 | 
			
		||||
  font-family: 'Korolev', sans-serif;
 | 
			
		||||
  font-size: 28px;
 | 
			
		||||
  line-height: 48px;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
.black .highlight {
 | 
			
		||||
  pre {
 | 
			
		||||
  background-color: #333;
 | 
			
		||||
  pre {
 | 
			
		||||
    color: #eee;
 | 
			
		||||
    background: inherit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .hll { display: block; background-color: darken($hover, 65%) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,27 +1,3 @@
 | 
			
		|||
/*
 | 
			
		||||
 * jQuery UI CSS Framework 1.8.7
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 | 
			
		||||
 * Dual licensed under the MIT or GPL Version 2 licenses.
 | 
			
		||||
 * http://jquery.org/license
 | 
			
		||||
 *
 | 
			
		||||
 * http://docs.jquery.com/UI/Theming/API
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Layout helpers
 | 
			
		||||
----------------------------------*/
 | 
			
		||||
.ui-helper-hidden { display: none; }
 | 
			
		||||
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
 | 
			
		||||
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
 | 
			
		||||
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
 | 
			
		||||
.ui-helper-clearfix { display: inline-block; }
 | 
			
		||||
/* required comment for clearfix to work in Opera \*/
 | 
			
		||||
* html .ui-helper-clearfix { height:1%; }
 | 
			
		||||
.ui-helper-clearfix { display:block; }
 | 
			
		||||
/* end clearfix */
 | 
			
		||||
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Interaction Cues
 | 
			
		||||
----------------------------------*/
 | 
			
		||||
.ui-state-disabled { cursor: default !important; }
 | 
			
		||||
| 
						 | 
				
			
			@ -140,26 +116,6 @@
 | 
			
		|||
/* Overlays */
 | 
			
		||||
.ui-widget-overlay { background: #262b33; opacity: .70;filter:Alpha(Opacity=70); }
 | 
			
		||||
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #000000; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
 | 
			
		||||
/*
 | 
			
		||||
 * jQuery UI Resizable 1.8.7
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 | 
			
		||||
 * Dual licensed under the MIT or GPL Version 2 licenses.
 | 
			
		||||
 * http://jquery.org/license
 | 
			
		||||
 *
 | 
			
		||||
 * http://docs.jquery.com/UI/Resizable#theming
 | 
			
		||||
 */
 | 
			
		||||
.ui-resizable { position: relative;}
 | 
			
		||||
.ui-resizable-handle { position: absolute; font-size: 0.1px; z-index: 999; display: block;}
 | 
			
		||||
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
 | 
			
		||||
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
 | 
			
		||||
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
 | 
			
		||||
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
 | 
			
		||||
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
 | 
			
		||||
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
 | 
			
		||||
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 | 
			
		||||
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 | 
			
		||||
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
 | 
			
		||||
/*
 | 
			
		||||
 * jQuery UI Selectable 1.8.7
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -240,34 +196,7 @@
 | 
			
		|||
  cursor: pointer;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * jQuery UI Slider 1.8.7
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 | 
			
		||||
 * Dual licensed under the MIT or GPL Version 2 licenses.
 | 
			
		||||
 * http://jquery.org/license
 | 
			
		||||
 *
 | 
			
		||||
 * http://docs.jquery.com/UI/Slider#theming
 | 
			
		||||
 */
 | 
			
		||||
.ui-slider { position: relative; text-align: left; background: #d7d7d7; z-index: 1; }
 | 
			
		||||
.ui-slider { -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; box-shadow: 0 1px 2px rgba(0,0,0,0.5) inset; }
 | 
			
		||||
.ui-slider .ui-slider-handle { background: url(slider_handles.png) 0px -23px no-repeat; position: absolute; z-index: 2; width: 23px; height: 23px; cursor: default; border: none; outline: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; }
 | 
			
		||||
.ui-slider  .ui-state-hover, .ui-slider  .ui-state-active { background-position: 0 0; }
 | 
			
		||||
.ui-slider .ui-slider-range { background: #a3cae0; position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
 | 
			
		||||
.ui-slider .ui-slider-range { -moz-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; -webkit-box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; box-shadow: 0 1px 2px rgba(17,35,45,0.6) inset; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.ui-slider-horizontal { height: 5px; }
 | 
			
		||||
.ui-slider-horizontal .ui-slider-handle { top: -8px; margin-left: -13px; }
 | 
			
		||||
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
 | 
			
		||||
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
 | 
			
		||||
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
 | 
			
		||||
 | 
			
		||||
.ui-slider-vertical { width: 5px; height: 100px; }
 | 
			
		||||
.ui-slider-vertical .ui-slider-handle { left: -8px; margin-left: 0; margin-bottom: -13px; }
 | 
			
		||||
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
 | 
			
		||||
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 | 
			
		||||
.ui-slider-vertical .ui-slider-range-max { top: 0; }
 | 
			
		||||
/*
 | 
			
		||||
 * jQuery UI Datepicker 1.8.7
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -326,45 +255,3 @@
 | 
			
		|||
.ui-datepicker table .ui-state-highlight { border-color: #ADE; }
 | 
			
		||||
.ui-datepicker-calendar .ui-state-default { background: transparent; border-color: #FFF; }
 | 
			
		||||
.ui-datepicker-calendar .ui-state-active { background: #D9EDF7; border-color: #ADE; color: #3A89A3; font-weight: bold; text-shadow: 0 1px 1px #fff; }
 | 
			
		||||
 | 
			
		||||
/* with multiple calendars */
 | 
			
		||||
.ui-datepicker.ui-datepicker-multi { width:auto; }
 | 
			
		||||
.ui-datepicker-multi .ui-datepicker-group { float:left; }
 | 
			
		||||
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
 | 
			
		||||
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
 | 
			
		||||
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
 | 
			
		||||
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
 | 
			
		||||
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
 | 
			
		||||
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
 | 
			
		||||
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
 | 
			
		||||
.ui-datepicker-row-break { clear:both; width:100%; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Extra Input Field Styling */
 | 
			
		||||
.ui-form textarea, .ui-form input:not([type="submit"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]) {
 | 
			
		||||
	padding: 3px;
 | 
			
		||||
	-webkit-border-radius: 2px;
 | 
			
		||||
	-moz-border-radius: 2px;
 | 
			
		||||
	border-radius: 2px;
 | 
			
		||||
	border: 1px solid #cecece;
 | 
			
		||||
	outline: none;
 | 
			
		||||
	-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.1) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.1) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	box-shadow: 0 1px 3px rgba(0,0,0,0.1) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
    -webkit-transition: all 250ms ease-in-out;
 | 
			
		||||
    -moz-transition: all 250ms ease-in-out;
 | 
			
		||||
    -o-transition: all 250ms ease-in-out;
 | 
			
		||||
    transition: all 250ms ease-in-out;
 | 
			
		||||
}
 | 
			
		||||
.ui-form textarea:hover, .ui-form input:not([type="submit"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):hover {
 | 
			
		||||
	border: 1px solid #bdbdbd;
 | 
			
		||||
	-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.2) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.2) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	box-shadow: 0 1px 3px rgba(0,0,0,0.2) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
}
 | 
			
		||||
.ui-form textarea:focus, .ui-form input:not([type="submit"]):not([type="button"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):focus {
 | 
			
		||||
	border: 1px solid #95bdd4;
 | 
			
		||||
	-webkit-box-shadow: 0 2px 3px rgba(161,202,226,0.5) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	-moz-box-shadow: 0 2px 3px rgba(161,202,226,0.5) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
	box-shadow: 0 2px 3px rgba(161,202,226,0.5) inset, 0 1px 0 rgba(255,255,255,0.2);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,144 +0,0 @@
 | 
			
		|||
/** Override bootstrap variables **/
 | 
			
		||||
$baseFontSize: 13px !default;
 | 
			
		||||
$baseLineHeight: 18px !default;
 | 
			
		||||
 | 
			
		||||
// BOOTSTRAP
 | 
			
		||||
@import "bootstrap";
 | 
			
		||||
@import "bootstrap/responsive-utilities";
 | 
			
		||||
@import "bootstrap/responsive-1200px-min";
 | 
			
		||||
 | 
			
		||||
// FONT AWESOME
 | 
			
		||||
@import "font-awesome";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Variables
 | 
			
		||||
 * Contains colors
 | 
			
		||||
 */
 | 
			
		||||
@import "variables.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Custom fonts
 | 
			
		||||
 * Contains @font-face font Korolev and default $monotype
 | 
			
		||||
 */
 | 
			
		||||
@import "fonts.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * General mixins.
 | 
			
		||||
 * Contains rounded borders, gradients and shades
 | 
			
		||||
 */
 | 
			
		||||
@import "mixins.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Header of application.
 | 
			
		||||
 * Contain application logo, search panel, profile icon
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/header.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Navigation menu of application.
 | 
			
		||||
 * Panel with links to pages depends on project, profile or admin area
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/nav.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This file represent some UI that can be changed
 | 
			
		||||
 * during web app restyle or theme select.
 | 
			
		||||
 *
 | 
			
		||||
 * Next items should be placed there
 | 
			
		||||
 * - link, button colors
 | 
			
		||||
 * - header restyles
 | 
			
		||||
 * - main menu restyles
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
@import "themes/ui_basic.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * UI themes:
 | 
			
		||||
 */
 | 
			
		||||
@import "themes/ui_mars.scss";
 | 
			
		||||
@import "themes/ui_modern.scss";
 | 
			
		||||
@import "themes/ui_gray.scss";
 | 
			
		||||
@import "themes/ui_color.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * GitLab bootstrap.
 | 
			
		||||
 * Overrides some styles of twitter bootstrap.
 | 
			
		||||
 * Also give some common classes for GitLab app
 | 
			
		||||
 */
 | 
			
		||||
@import "gitlab_bootstrap/common.scss";
 | 
			
		||||
@import "gitlab_bootstrap/typography.scss";
 | 
			
		||||
@import "gitlab_bootstrap/buttons.scss";
 | 
			
		||||
@import "gitlab_bootstrap/blocks.scss";
 | 
			
		||||
@import "gitlab_bootstrap/files.scss";
 | 
			
		||||
@import "gitlab_bootstrap/tables.scss";
 | 
			
		||||
@import "gitlab_bootstrap/lists.scss";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Most of application styles placed here.
 | 
			
		||||
 * This file represent common UI that should not be changed between themes
 | 
			
		||||
 * or project restyling like form width or user avatar class or commit title
 | 
			
		||||
 *
 | 
			
		||||
 * TODO: clean it
 | 
			
		||||
 */
 | 
			
		||||
@import "common.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Styles necessary to support JS behaviours.
 | 
			
		||||
 */
 | 
			
		||||
@import "behaviors.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Styles related to specific part of app
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/commits.scss";
 | 
			
		||||
@import "sections/issues.scss";
 | 
			
		||||
@import "sections/projects.scss";
 | 
			
		||||
@import "sections/merge_requests.scss";
 | 
			
		||||
@import "sections/graph.scss";
 | 
			
		||||
@import "sections/events.scss";
 | 
			
		||||
@import "sections/themes.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This scss file redefine chozen selectbox styles for
 | 
			
		||||
 * project Branch/Tag select element
 | 
			
		||||
 */
 | 
			
		||||
@import "ref_select.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Code (files list) styles. Browsing project files there
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/tree.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This file represent notes(comments) styles
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/notes.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This file represent profile styles
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/profile.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Devise styles
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/login.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CODE HIGHTLIGHT BASE
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
@import "highlight/white.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CODE HIGHTLIGHT DARK schema
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
@import "highlight/dark.scss";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * File Editor styles
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
@import "sections/editor.scss";
 | 
			
		||||
| 
						 | 
				
			
			@ -232,8 +232,6 @@
 | 
			
		|||
 | 
			
		||||
/** COMMIT ROW **/
 | 
			
		||||
.commit {
 | 
			
		||||
  @extend .wll;
 | 
			
		||||
 | 
			
		||||
  .browse_code_link_holder {
 | 
			
		||||
    @extend .span2;
 | 
			
		||||
    float: right;
 | 
			
		||||
| 
						 | 
				
			
			@ -305,3 +303,17 @@
 | 
			
		|||
  color: #fff;
 | 
			
		||||
  font-family: $monospace;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.commits-compare-switch{
 | 
			
		||||
  background: url("switch_icon.png") no-repeat center center;
 | 
			
		||||
  width: 16px;
 | 
			
		||||
  height: 18px;
 | 
			
		||||
  text-indent: -9999px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin-right: 9px;
 | 
			
		||||
  border: 1px solid #DDD;
 | 
			
		||||
  @include border-radius(4px);
 | 
			
		||||
  padding: 4px;
 | 
			
		||||
  background-color: #EEE;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,6 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
.event-item {
 | 
			
		||||
  min-height: 40px;
 | 
			
		||||
  border-bottom: 1px solid #eee;
 | 
			
		||||
  .event-title {
 | 
			
		||||
    color: #333;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,14 +49,18 @@
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .avatar {
 | 
			
		||||
    width: 32px;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -3px;
 | 
			
		||||
  }
 | 
			
		||||
  .event_icon {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    float: right;
 | 
			
		||||
    border: 1px solid #EEE;
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
    @include border-radius(5px);
 | 
			
		||||
    background: #F9F9F9;
 | 
			
		||||
    margin-left: 10px;
 | 
			
		||||
    top: -6px;
 | 
			
		||||
    img {
 | 
			
		||||
      width: 20px;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -71,9 +74,8 @@
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  padding: 15px 5px;
 | 
			
		||||
  padding: 16px 5px;
 | 
			
		||||
  &:last-child { border:none }
 | 
			
		||||
  .wll:hover { background:none }
 | 
			
		||||
 | 
			
		||||
  .event_commits {
 | 
			
		||||
    margin-top: 5px;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,14 +44,9 @@ header {
 | 
			
		|||
        background: url('logo_dark.png') no-repeat 0px 2px;
 | 
			
		||||
        float: left;
 | 
			
		||||
        margin-left: 2px;
 | 
			
		||||
        font-size: 30px;
 | 
			
		||||
        line-height: 48px;
 | 
			
		||||
        font-weight: normal;
 | 
			
		||||
        color: $style_color;
 | 
			
		||||
        text-shadow: 0 1px 1px #FFF;
 | 
			
		||||
        padding-left: 45px;
 | 
			
		||||
        height: 40px;
 | 
			
		||||
        font-family: 'Korolev', sans-serif;
 | 
			
		||||
        @include header-font;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -66,12 +61,7 @@ header {
 | 
			
		|||
    float: left;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    margin-right: 30px;
 | 
			
		||||
    font-size: 30px;
 | 
			
		||||
    line-height: 48px;
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    color: $style_color;
 | 
			
		||||
    text-shadow: 0 1px 1px #FFF;
 | 
			
		||||
    font-family: 'Korolev', sans-serif;
 | 
			
		||||
    @include header-font;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +162,7 @@ header {
 | 
			
		|||
    display: none;
 | 
			
		||||
    z-index: 100000;
 | 
			
		||||
    @include border-radius(4px);
 | 
			
		||||
    width: 100px;
 | 
			
		||||
    width: 130px;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 5px;
 | 
			
		||||
    top: 38px;
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +171,7 @@ header {
 | 
			
		|||
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
 | 
			
		||||
    a {
 | 
			
		||||
      color: #fff;
 | 
			
		||||
      padding: 7px 10px;
 | 
			
		||||
      padding: 12px 15px;
 | 
			
		||||
      display: block;
 | 
			
		||||
      text-shadow: none;
 | 
			
		||||
      border-bottom: 1px solid #666;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,12 +121,3 @@ input.check_all_issues {
 | 
			
		|||
#update_status {
 | 
			
		||||
  width: 100px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Milestones list
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
.milestone {
 | 
			
		||||
  @extend .wll;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -136,9 +136,3 @@ li.merge_request {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.status-badge {
 | 
			
		||||
  height: 32px;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  @include border-radius(5px);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,15 +3,13 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
ul.main_menu {
 | 
			
		||||
  @include border-radius(4px);
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  margin: 30px 0;
 | 
			
		||||
  border: 1px solid #BBB;
 | 
			
		||||
  margin-top: 10px;
 | 
			
		||||
  border-bottom: 1px solid #DDD;
 | 
			
		||||
  height: 37px;
 | 
			
		||||
  @include bg-gray-gradient;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  @include shade;
 | 
			
		||||
  .count {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -1px;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,9 +22,6 @@ ul.main_menu {
 | 
			
		|||
    line-height: 14px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    color: #777;
 | 
			
		||||
    background: #f2f2f2;
 | 
			
		||||
    border-top: 1px solid #CCC;
 | 
			
		||||
    @include border-radius(8px);
 | 
			
		||||
  }
 | 
			
		||||
  .label {
 | 
			
		||||
    background: $hover;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,23 +33,10 @@ ul.main_menu {
 | 
			
		|||
    margin: 0;
 | 
			
		||||
    display: table-cell;
 | 
			
		||||
    width: 1%;
 | 
			
		||||
    border-right: 1px solid #DDD;
 | 
			
		||||
    border-left: 1px solid #EEE;
 | 
			
		||||
    border-bottom: 2px solid #CFCFCF;
 | 
			
		||||
 | 
			
		||||
    &:first-child{
 | 
			
		||||
      @include border-radius(5px 0 0 5px);
 | 
			
		||||
      border-left: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.active {
 | 
			
		||||
      background-color: #D5D5D5;
 | 
			
		||||
      border-right: 1px solid #BBB;
 | 
			
		||||
      border-left: 1px solid #BBB;
 | 
			
		||||
      @include border-radius(0 0 1px 1px);
 | 
			
		||||
      &:first-child{
 | 
			
		||||
        border-bottom: none;
 | 
			
		||||
        border-left: none;
 | 
			
		||||
      border-bottom: 2px solid #474D57;
 | 
			
		||||
      a {
 | 
			
		||||
        color: $style_color;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,10 +55,10 @@ ul.main_menu {
 | 
			
		|||
  a {
 | 
			
		||||
    display: block;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    height: 35px;
 | 
			
		||||
    line-height: 36px;
 | 
			
		||||
    color: $style_color;
 | 
			
		||||
    color: #777;
 | 
			
		||||
    text-shadow: 0 1px 1px white;
 | 
			
		||||
    padding: 0 10px;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,11 @@
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  .side {
 | 
			
		||||
    @extend .span4;
 | 
			
		||||
    @extend .right;
 | 
			
		||||
 | 
			
		||||
    .groups_box,
 | 
			
		||||
    .projects_box {
 | 
			
		||||
      h5 {
 | 
			
		||||
      > h5 {
 | 
			
		||||
        color: $style_color;
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
        text-shadow: 0 1px 1px #fff;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,20 +16,8 @@
 | 
			
		|||
        line-height: 32px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
      }
 | 
			
		||||
      ul {
 | 
			
		||||
        li {
 | 
			
		||||
          padding: 0;
 | 
			
		||||
          a {
 | 
			
		||||
            display: block;
 | 
			
		||||
            .group_name {
 | 
			
		||||
              font-size: 14px;
 | 
			
		||||
              line-height: 18px;
 | 
			
		||||
            }
 | 
			
		||||
            .project_name {
 | 
			
		||||
              color: #4fa2bd;
 | 
			
		||||
              font-size: 14px;
 | 
			
		||||
              line-height: 18px;
 | 
			
		||||
            }
 | 
			
		||||
      .nav-projects-tabs li { padding: 0; }
 | 
			
		||||
      .well-list {
 | 
			
		||||
        .arrow {
 | 
			
		||||
          float: right;
 | 
			
		||||
          padding: 10px;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,9 +32,6 @@
 | 
			
		|||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      @extend .leftbar;
 | 
			
		||||
      @extend .ui-box;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -117,3 +101,25 @@
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ul.nav.nav-projects-tabs {
 | 
			
		||||
  @extend .nav-tabs;
 | 
			
		||||
 | 
			
		||||
  padding-left: 8px;
 | 
			
		||||
 | 
			
		||||
  li {
 | 
			
		||||
    a {
 | 
			
		||||
      padding: 4px 20px;
 | 
			
		||||
      margin-top: 2px;
 | 
			
		||||
      border-color: #DDD;
 | 
			
		||||
      background-color: #EEE;
 | 
			
		||||
      text-shadow: 0 1px 1px white;
 | 
			
		||||
      color: #555;
 | 
			
		||||
    }
 | 
			
		||||
    &.active {
 | 
			
		||||
      a {
 | 
			
		||||
        font-weight: bold;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
.snippet.file_holder {
 | 
			
		||||
  .file_title {
 | 
			
		||||
    .snippet-file-name {
 | 
			
		||||
      position: relative;
 | 
			
		||||
      top: -4px;
 | 
			
		||||
      left: -4px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
.votes {
 | 
			
		||||
  font-size: 13px;
 | 
			
		||||
  line-height: 15px;
 | 
			
		||||
  .progress {
 | 
			
		||||
    height: 4px;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    .bar {
 | 
			
		||||
      float: left;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
    }
 | 
			
		||||
    .bar-success {
 | 
			
		||||
      @include linear-gradient(#62C462, #51A351);
 | 
			
		||||
      background-color: #468847;
 | 
			
		||||
    }
 | 
			
		||||
    .bar-danger {
 | 
			
		||||
      @include linear-gradient(#EE5F5B, #BD362F);
 | 
			
		||||
      background-color: #B94A48;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .upvotes {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    color: #468847;
 | 
			
		||||
  }
 | 
			
		||||
  .downvotes {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    color: #B94A48;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.votes-block {
 | 
			
		||||
  margin: 14px 6px 6px 0;
 | 
			
		||||
  .downvotes {
 | 
			
		||||
    float: right;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.votes-inline {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  margin: 0 8px;
 | 
			
		||||
  .progress {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding: 0 0 2px;
 | 
			
		||||
    width: 45px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,18 +4,6 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
.ui_basic {
 | 
			
		||||
  /*
 | 
			
		||||
   * Common styles
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  a {
 | 
			
		||||
    color: $link_color;
 | 
			
		||||
    &:hover {
 | 
			
		||||
      text-decoration: none;
 | 
			
		||||
      color: $primary_color;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .app_logo {
 | 
			
		||||
    .separator {
 | 
			
		||||
      margin-left: 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,9 @@ class ProjectUpdateContext < BaseContext
 | 
			
		|||
  def execute(role = :default)
 | 
			
		||||
    namespace_id = params[:project].delete(:namespace_id)
 | 
			
		||||
 | 
			
		||||
    if namespace_id.present?
 | 
			
		||||
    allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
 | 
			
		||||
 | 
			
		||||
    if allowed_transfer && namespace_id.present?
 | 
			
		||||
      if namespace_id == Namespace.global_id
 | 
			
		||||
        if project.namespace.present?
 | 
			
		||||
          # Transfer to global namespace from anyone
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ class Admin::GroupsController < AdminController
 | 
			
		|||
  before_filter :group, only: [:edit, :show, :update, :destroy, :project_update]
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @groups = Group.scoped
 | 
			
		||||
    @groups = Group.order('name ASC')
 | 
			
		||||
    @groups = @groups.search(params[:name]) if params[:name].present?
 | 
			
		||||
    @groups = @groups.page(params[:page]).per(20)
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ class Admin::GroupsController < AdminController
 | 
			
		|||
    @projects = Project.scoped
 | 
			
		||||
    @projects = @projects.not_in_group(@group) if @group.projects.present?
 | 
			
		||||
    @projects = @projects.all
 | 
			
		||||
    @projects.reject!(&:empty_repo?)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def new
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,13 @@ class Admin::ProjectsController < AdminController
 | 
			
		|||
  def index
 | 
			
		||||
    @projects = Project.scoped
 | 
			
		||||
    @projects = @projects.where(namespace_id: params[:namespace_id]) if params[:namespace_id].present?
 | 
			
		||||
    @projects = @projects.where(namespace_id: nil) if params[:namespace_id] == Namespace.global_id
 | 
			
		||||
    @projects = @projects.search(params[:name]) if params[:name].present?
 | 
			
		||||
    @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
    @users = User.scoped
 | 
			
		||||
    @users = User.active
 | 
			
		||||
    @users = @users.not_in_project(@project) if @project.users.present?
 | 
			
		||||
    @users = @users.all
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ class Admin::UsersController < AdminController
 | 
			
		|||
    @admin_users = User.scoped
 | 
			
		||||
    @admin_users = @admin_users.filter(params[:filter])
 | 
			
		||||
    @admin_users = @admin_users.search(params[:name]) if params[:name].present?
 | 
			
		||||
    @admin_users = @admin_users.order("updated_at DESC").page(params[:page])
 | 
			
		||||
    @admin_users = @admin_users.order("name ASC").page(params[:page])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ class Admin::UsersController < AdminController
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
  def new
 | 
			
		||||
    @admin_user = User.new({ projects_limit: Gitlab.config.default_projects_limit }, as: :admin)
 | 
			
		||||
    @admin_user = User.new({ projects_limit: Gitlab.config.gitlab.default_projects_limit }, as: :admin)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def edit
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,10 @@ class ApplicationController < ActionController::Base
 | 
			
		|||
    render file: Rails.root.join("public", "404"), layout: false, status: "404"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def render_403
 | 
			
		||||
    render file: Rails.root.join("public", "403"), layout: false, status: "403"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def require_non_empty_project
 | 
			
		||||
    redirect_to @project if @project.empty_repo?
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ class DashboardController < ApplicationController
 | 
			
		|||
  def index
 | 
			
		||||
    @groups = current_user.authorized_groups
 | 
			
		||||
 | 
			
		||||
    @has_authorized_projects = @projects.count > 0
 | 
			
		||||
 | 
			
		||||
    @projects = case params[:scope]
 | 
			
		||||
                when 'personal' then
 | 
			
		||||
                  @projects.personal(current_user)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ class GroupsController < ApplicationController
 | 
			
		|||
 | 
			
		||||
  # Get authored or assigned open merge requests
 | 
			
		||||
  def merge_requests
 | 
			
		||||
    @merge_requests = current_user.cared_merge_requests
 | 
			
		||||
    @merge_requests = current_user.cared_merge_requests.opened
 | 
			
		||||
    @merge_requests = @merge_requests.of_group(@group).recent.page(params[:page]).per(20)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ class GroupsController < ApplicationController
 | 
			
		|||
  def people
 | 
			
		||||
    @project = group.projects.find(params[:project_id]) if params[:project_id]
 | 
			
		||||
    @users = @project ? @project.users : group.users
 | 
			
		||||
    @users.sort_by!(&:name)
 | 
			
		||||
 | 
			
		||||
    if @project
 | 
			
		||||
      @team_member = @project.users_projects.new
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
class IssuesController < ProjectResourceController
 | 
			
		||||
  before_filter :module_enabled
 | 
			
		||||
  before_filter :issue, only: [:edit, :update, :destroy, :show]
 | 
			
		||||
  before_filter :issue, only: [:edit, :update, :show]
 | 
			
		||||
 | 
			
		||||
  # Allow read any issue
 | 
			
		||||
  before_filter :authorize_read_issue!
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +11,6 @@ class IssuesController < ProjectResourceController
 | 
			
		|||
  # Allow modify issue
 | 
			
		||||
  before_filter :authorize_modify_issue!, only: [:edit, :update]
 | 
			
		||||
 | 
			
		||||
  # Allow destroy issue
 | 
			
		||||
  before_filter :authorize_admin_issue!, only: [:destroy]
 | 
			
		||||
 | 
			
		||||
  respond_to :js, :html
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
| 
						 | 
				
			
			@ -79,15 +76,6 @@ class IssuesController < ProjectResourceController
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def destroy
 | 
			
		||||
    @issue.destroy
 | 
			
		||||
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.html { redirect_to project_issues_path }
 | 
			
		||||
      format.js { render nothing: true }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def sort
 | 
			
		||||
    return render_404 unless can?(current_user, :admin_issue, @project)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
class MergeRequestsController < ProjectResourceController
 | 
			
		||||
  before_filter :module_enabled
 | 
			
		||||
  before_filter :merge_request, only: [:edit, :update, :destroy, :show, :commits, :diffs, :automerge, :automerge_check]
 | 
			
		||||
  before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]
 | 
			
		||||
  before_filter :validates_merge_request, only: [:show, :diffs]
 | 
			
		||||
  before_filter :define_show_vars, only: [:show, :diffs]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,9 +13,6 @@ class MergeRequestsController < ProjectResourceController
 | 
			
		|||
  # Allow modify merge_request
 | 
			
		||||
  before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
 | 
			
		||||
 | 
			
		||||
  # Allow destroy merge_request
 | 
			
		||||
  before_filter :authorize_admin_merge_request!, only: [:destroy]
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			@ -90,14 +87,6 @@ class MergeRequestsController < ProjectResourceController
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def destroy
 | 
			
		||||
    @merge_request.destroy
 | 
			
		||||
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.html { redirect_to project_merge_requests_url(@project) }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def branch_from
 | 
			
		||||
    @commit = project.commit(params[:ref])
 | 
			
		||||
    @commit = CommitDecorator.decorate(@commit)
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +97,13 @@ class MergeRequestsController < ProjectResourceController
 | 
			
		|||
    @commit = CommitDecorator.decorate(@commit)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def ci_status
 | 
			
		||||
    status = project.gitlab_ci_service.commit_status(merge_request.last_commit.sha)
 | 
			
		||||
    response = { status: status }
 | 
			
		||||
 | 
			
		||||
    render json: response
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  def merge_request
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,11 +12,12 @@ class MilestonesController < ProjectResourceController
 | 
			
		|||
 | 
			
		||||
  def index
 | 
			
		||||
    @milestones = case params[:f]
 | 
			
		||||
                  when 'all'; @project.milestones
 | 
			
		||||
                  else @project.milestones.active
 | 
			
		||||
                  when 'all'; @project.milestones.order("closed, due_date DESC")
 | 
			
		||||
                  when 'closed'; @project.milestones.closed.order("due_date DESC")
 | 
			
		||||
                  else @project.milestones.active.order("due_date ASC")
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
    @milestones = @milestones.includes(:project).order("due_date")
 | 
			
		||||
    @milestones = @milestones.includes(:project)
 | 
			
		||||
    @milestones = @milestones.page(params[:page]).per(20)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +43,7 @@ class MilestonesController < ProjectResourceController
 | 
			
		|||
 | 
			
		||||
  def create
 | 
			
		||||
    @milestone = @project.milestones.new(params[:milestone])
 | 
			
		||||
    @milestone.author_id_of_changes = current_user.id
 | 
			
		||||
 | 
			
		||||
    if @milestone.save
 | 
			
		||||
      redirect_to project_milestone_path(@project, @milestone)
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +53,7 @@ class MilestonesController < ProjectResourceController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def update
 | 
			
		||||
    @milestone.update_attributes(params[:milestone])
 | 
			
		||||
    @milestone.update_attributes(params[:milestone].merge(author_id_of_changes: current_user.id))
 | 
			
		||||
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.js
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
 | 
			
		||||
  Gitlab.config.omniauth_providers.each do |provider|
 | 
			
		||||
  Gitlab.config.omniauth.providers.each do |provider|
 | 
			
		||||
    define_method provider['name'] do
 | 
			
		||||
      handle_omniauth
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,10 @@ class ProjectsController < ProjectResourceController
 | 
			
		|||
        format.js
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  rescue Project::TransferError => ex
 | 
			
		||||
    @error = ex
 | 
			
		||||
    render :update_failed
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def show
 | 
			
		||||
| 
						 | 
				
			
			@ -86,12 +90,18 @@ class ProjectsController < ProjectResourceController
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def graph
 | 
			
		||||
    respond_to do |format|
 | 
			
		||||
      format.html
 | 
			
		||||
      format.json do
 | 
			
		||||
        graph = Gitlab::Graph::JsonBuilder.new(project)
 | 
			
		||||
 | 
			
		||||
    @days_json, @commits_json = graph.days_json, graph.commits_json
 | 
			
		||||
        render :json => graph.to_json
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def destroy
 | 
			
		||||
    return access_denied! unless can?(current_user, :remove_project, project)
 | 
			
		||||
 | 
			
		||||
    # Disable the UsersProject update_repository call, otherwise it will be
 | 
			
		||||
    # called once for every person removed from the project
 | 
			
		||||
    UsersProject.skip_callback(:destroy, :after, :update_repository)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ class SnippetsController < ProjectResourceController
 | 
			
		|||
  respond_to :html
 | 
			
		||||
 | 
			
		||||
  def index
 | 
			
		||||
    @snippets = @project.snippets
 | 
			
		||||
    @snippets = @project.snippets.fresh
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def new
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ class CommitDecorator < ApplicationDecorator
 | 
			
		|||
    source_name = send "#{options[:source]}_name".to_sym
 | 
			
		||||
    source_email = send "#{options[:source]}_email".to_sym
 | 
			
		||||
    text = if options[:avatar]
 | 
			
		||||
            avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size]
 | 
			
		||||
            avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: ""
 | 
			
		||||
            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
 | 
			
		||||
          else
 | 
			
		||||
            source_name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
require 'digest/md5'
 | 
			
		||||
require 'uri'
 | 
			
		||||
 | 
			
		||||
module ApplicationHelper
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,13 +31,15 @@ module ApplicationHelper
 | 
			
		|||
    args.any? { |v| v.to_s.downcase == action_name }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def gravatar_icon(user_email = '', size = 40)
 | 
			
		||||
    if Gitlab.config.disable_gravatar? || user_email.blank?
 | 
			
		||||
  def gravatar_icon(user_email = '', size = nil)
 | 
			
		||||
    size = 40 if size.nil? || size <= 0
 | 
			
		||||
 | 
			
		||||
    if !Gitlab.config.gravatar.enabled || user_email.blank?
 | 
			
		||||
      'no_avatar.png'
 | 
			
		||||
    else
 | 
			
		||||
      gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
 | 
			
		||||
      gravatar_url = request.ssl? ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
 | 
			
		||||
      user_email.strip!
 | 
			
		||||
      "#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=mm"
 | 
			
		||||
      sprintf(gravatar_url, {:hash => Digest::MD5.hexdigest(user_email.downcase), :email => URI.escape(user_email), :size => size})
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +48,7 @@ module ApplicationHelper
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def web_app_url
 | 
			
		||||
    "#{request_protocol}://#{Gitlab.config.web_host}/"
 | 
			
		||||
    "#{request_protocol}://#{Gitlab.config.gitlab.host}/"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def last_commit(project)
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +95,7 @@ module ApplicationHelper
 | 
			
		|||
      { label: "API Help", url: help_api_path },
 | 
			
		||||
      { label: "Markdown Help", url: help_markdown_path },
 | 
			
		||||
      { label: "SSH Keys Help", url: help_ssh_path },
 | 
			
		||||
      { label: "Gitlab Rake Tasks Help", url: help_raketasks_path },
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    project_nav = []
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,28 +4,6 @@ module IssuesHelper
 | 
			
		|||
    project_issues_path project, params
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_issue_assignee(issue)
 | 
			
		||||
    project = issue.project
 | 
			
		||||
 | 
			
		||||
    tm = project.team_member_by_id(issue.assignee_id)
 | 
			
		||||
    if tm
 | 
			
		||||
      link_to issue.assignee_name, project_team_member_path(project, tm), class: "author_link"
 | 
			
		||||
    else
 | 
			
		||||
      issue.assignee_name
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_issue_author(issue)
 | 
			
		||||
    project = issue.project
 | 
			
		||||
 | 
			
		||||
    tm = project.team_member_by_id(issue.author_id)
 | 
			
		||||
    if tm
 | 
			
		||||
      link_to issue.author_name, project_team_member_path(project, tm), class: "author_link"
 | 
			
		||||
    else
 | 
			
		||||
      issue.author_name
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def issue_css_classes issue
 | 
			
		||||
    classes = "issue"
 | 
			
		||||
    classes << " closed" if issue.closed
 | 
			
		||||
| 
						 | 
				
			
			@ -52,4 +30,14 @@ module IssuesHelper
 | 
			
		|||
      open: "open"
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def labels_autocomplete_source
 | 
			
		||||
    labels = @project.issues_labels.order('count DESC')
 | 
			
		||||
    labels = labels.map{ |l| { label: l.name, value: l.name } }
 | 
			
		||||
    labels.to_json
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def issues_active_milestones
 | 
			
		||||
    @project.milestones.active.order("id desc").all
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,26 +1,4 @@
 | 
			
		|||
module MergeRequestsHelper
 | 
			
		||||
  def link_to_merge_request_assignee(merge_request)
 | 
			
		||||
    project = merge_request.project
 | 
			
		||||
 | 
			
		||||
    tm = project.team_member_by_id(merge_request.assignee_id)
 | 
			
		||||
    if tm
 | 
			
		||||
      link_to merge_request.assignee_name, project_team_member_path(project, tm), class: "author_link"
 | 
			
		||||
    else
 | 
			
		||||
      merge_request.assignee_name
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_merge_request_author(merge_request)
 | 
			
		||||
    project = merge_request.project
 | 
			
		||||
 | 
			
		||||
    tm = project.team_member_by_id(merge_request.author_id)
 | 
			
		||||
    if tm
 | 
			
		||||
      link_to merge_request.author_name, project_team_member_path(project, tm), class: "author_link"
 | 
			
		||||
    else
 | 
			
		||||
      merge_request.author_name
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def new_mr_path_from_push_event(event)
 | 
			
		||||
    new_project_merge_request_path(
 | 
			
		||||
      event.project,
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +17,7 @@ module MergeRequestsHelper
 | 
			
		|||
    classes
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def ci_status_path
 | 
			
		||||
    @project.gitlab_ci_service.commit_badge_path(@merge_request.last_commit.sha)
 | 
			
		||||
  def ci_build_details_path merge_request
 | 
			
		||||
    merge_request.project.gitlab_ci_service.build_page(merge_request.last_commit.sha)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,11 +8,49 @@ module ProjectsHelper
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_project project
 | 
			
		||||
    link_to project.name, project
 | 
			
		||||
    link_to project do
 | 
			
		||||
      title = content_tag(:strong, project.name)
 | 
			
		||||
 | 
			
		||||
      if project.namespace
 | 
			
		||||
        namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'tiny')
 | 
			
		||||
        title = namespace + title
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      title
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def link_to_member(project, author)
 | 
			
		||||
    return "(deleted)" unless author
 | 
			
		||||
 | 
			
		||||
    # Build avatar image tag
 | 
			
		||||
    avatar = image_tag(gravatar_icon(author.try(:email)), width: 16, class: "lil_av")
 | 
			
		||||
 | 
			
		||||
    # Build name strong tag
 | 
			
		||||
    name = content_tag :strong, author.name, class: 'author'
 | 
			
		||||
 | 
			
		||||
    author_html = avatar + name
 | 
			
		||||
 | 
			
		||||
    tm = project.team_member_by_id(author)
 | 
			
		||||
 | 
			
		||||
    content_tag :span, class: 'member-link' do
 | 
			
		||||
      if tm
 | 
			
		||||
        link_to author_html, project_team_member_path(project, tm), class: "author_link"
 | 
			
		||||
      else
 | 
			
		||||
        author_html
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def tm_path team_member
 | 
			
		||||
    project_team_member_path(@project, team_member)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
  def project_title project
 | 
			
		||||
    if project.group
 | 
			
		||||
      project.name_with_namespace
 | 
			
		||||
    else
 | 
			
		||||
      project.name
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ module TabHelper
 | 
			
		|||
      return "active" if current_page?(controller: "projects", action: action, id: @project)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
 | 
			
		||||
    if ['snippets', 'services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
 | 
			
		||||
     "active"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,11 @@ class Notify < ActionMailer::Base
 | 
			
		|||
  add_template_helper ApplicationHelper
 | 
			
		||||
  add_template_helper GitlabMarkdownHelper
 | 
			
		||||
 | 
			
		||||
  default_url_options[:host]     = Gitlab.config.web_host
 | 
			
		||||
  default_url_options[:protocol] = Gitlab.config.web_protocol
 | 
			
		||||
  default_url_options[:port]     = Gitlab.config.web_port if Gitlab.config.web_custom_port?
 | 
			
		||||
  default_url_options[:host]     = Gitlab.config.gitlab.host
 | 
			
		||||
  default_url_options[:protocol] = Gitlab.config.gitlab.protocol
 | 
			
		||||
  default_url_options[:port]     = Gitlab.config.gitlab.port if Gitlab.config.gitlab_on_non_standard_port?
 | 
			
		||||
 | 
			
		||||
  default from: Gitlab.config.email_from
 | 
			
		||||
  default from: Gitlab.config.gitlab.email_from
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ class Notify < ActionMailer::Base
 | 
			
		|||
  def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
 | 
			
		||||
    @issue = Issue.find issue_id
 | 
			
		||||
    @issue_status = status
 | 
			
		||||
    @project = @issue.project
 | 
			
		||||
    @updated_by = User.find updated_by_user_id
 | 
			
		||||
    mail(to: recipient(recipient_id),
 | 
			
		||||
        subject: subject("changed issue ##{@issue.id}", @issue.title))
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +103,12 @@ class Notify < ActionMailer::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  def project_was_moved_email(user_project_id)
 | 
			
		||||
    @users_project = UsersProject.find user_project_id
 | 
			
		||||
    @project = @users_project.project
 | 
			
		||||
    mail(to: @users_project.user.email,
 | 
			
		||||
         subject: subject("project was moved"))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  #
 | 
			
		||||
  # User
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,9 +17,7 @@ class Ability
 | 
			
		|||
 | 
			
		||||
      # Rules based on role in project
 | 
			
		||||
      if project.master_access_for?(user)
 | 
			
		||||
        # TODO: replace with master rules.
 | 
			
		||||
        # Only allow project administration for namespace owners
 | 
			
		||||
        rules << project_admin_rules
 | 
			
		||||
        rules << project_master_rules
 | 
			
		||||
 | 
			
		||||
      elsif project.dev_access_for?(user)
 | 
			
		||||
        rules << project_dev_rules
 | 
			
		||||
| 
						 | 
				
			
			@ -93,13 +91,16 @@ class Ability
 | 
			
		|||
        :admin_merge_request,
 | 
			
		||||
        :admin_note,
 | 
			
		||||
        :accept_mr,
 | 
			
		||||
        :admin_wiki
 | 
			
		||||
        :admin_wiki,
 | 
			
		||||
        :admin_project
 | 
			
		||||
      ]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def project_admin_rules
 | 
			
		||||
      project_master_rules + [
 | 
			
		||||
        :admin_project
 | 
			
		||||
        :change_namespace,
 | 
			
		||||
        :rename_project,
 | 
			
		||||
        :remove_project
 | 
			
		||||
      ]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,14 +87,10 @@ class Commit
 | 
			
		|||
      last = project.commit(from.try(:strip))
 | 
			
		||||
 | 
			
		||||
      if first && last
 | 
			
		||||
        commits = [first, last].sort_by(&:created_at)
 | 
			
		||||
        younger = commits.first
 | 
			
		||||
        older = commits.last
 | 
			
		||||
 | 
			
		||||
        result[:same] = (younger.id == older.id)
 | 
			
		||||
        result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
 | 
			
		||||
        result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
 | 
			
		||||
        result[:commit] = Commit.new(older)
 | 
			
		||||
        result[:same] = (first.id == last.id)
 | 
			
		||||
        result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
 | 
			
		||||
        result[:diffs] = project.repo.diff(last.id, first.id) rescue []
 | 
			
		||||
        result[:commit] = Commit.new(first)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      result
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +159,8 @@ class Commit
 | 
			
		|||
    while !lines.first.start_with?("diff --git") do
 | 
			
		||||
      lines.shift
 | 
			
		||||
    end
 | 
			
		||||
    lines.pop if lines.last =~ /^[\d.]+$/ # Git version
 | 
			
		||||
    lines.pop if lines.last == "-- "      # end of diff
 | 
			
		||||
    lines.join("\n")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
class Event < ActiveRecord::Base
 | 
			
		||||
  include NoteEvent
 | 
			
		||||
  include PushEvent
 | 
			
		||||
 | 
			
		||||
  attr_accessible :project, :action, :data, :author_id, :project_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,12 +59,14 @@ class Event < ActiveRecord::Base
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Next events currently enabled for system
 | 
			
		||||
  #  - push
 | 
			
		||||
  #  - new issue
 | 
			
		||||
  #  - merge request
 | 
			
		||||
  def allowed?
 | 
			
		||||
    push? || issue? || merge_request? || membership_changed?
 | 
			
		||||
  def proper?
 | 
			
		||||
    if push?
 | 
			
		||||
      true
 | 
			
		||||
    elsif membership_changed?
 | 
			
		||||
      true
 | 
			
		||||
    else
 | 
			
		||||
      (issue? || merge_request? || note? || milestone?) && target
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def project_name
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +97,14 @@ class Event < ActiveRecord::Base
 | 
			
		|||
    action == self.class::Reopened
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def milestone?
 | 
			
		||||
    target_type == "Milestone"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note?
 | 
			
		||||
    target_type == "Note"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def issue?
 | 
			
		||||
    target_type == "Issue"
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,4 +36,22 @@ class GitlabCiService < Service
 | 
			
		|||
  def commit_badge_path sha
 | 
			
		||||
    project_url + "/status?sha=#{sha}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def commit_status_path sha
 | 
			
		||||
    project_url + "/builds/#{sha}/status.json?token=#{token}"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def commit_status sha
 | 
			
		||||
    response = HTTParty.get(commit_status_path(sha))
 | 
			
		||||
 | 
			
		||||
    if response.code == 200 and response["status"]
 | 
			
		||||
      response["status"]
 | 
			
		||||
    else
 | 
			
		||||
      :error
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def build_page sha
 | 
			
		||||
    project_url + "/builds/#{sha}"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,7 +204,7 @@ class MergeRequest < ActiveRecord::Base
 | 
			
		|||
 | 
			
		||||
  def mr_and_commit_notes
 | 
			
		||||
    commit_ids = commits.map(&:id)
 | 
			
		||||
    Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND noteable_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
 | 
			
		||||
    Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns the raw diff for this merge request
 | 
			
		||||
| 
						 | 
				
			
			@ -220,4 +220,8 @@ class MergeRequest < ActiveRecord::Base
 | 
			
		|||
  def to_patch
 | 
			
		||||
    project.repo.git.format_patch({timeout: 30, raise: true, stdout: true}, "#{target_branch}..#{source_branch}")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def last_commit_short_sha
 | 
			
		||||
    @last_commit_short_sha ||= last_commit.sha[0..10]
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,18 +13,26 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
class Milestone < ActiveRecord::Base
 | 
			
		||||
  attr_accessible :title, :description, :due_date, :closed
 | 
			
		||||
  attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
 | 
			
		||||
  attr_accessor :author_id_of_changes
 | 
			
		||||
 | 
			
		||||
  belongs_to :project
 | 
			
		||||
  has_many :issues
 | 
			
		||||
  has_many :merge_requests
 | 
			
		||||
 | 
			
		||||
  scope :active, where(closed: false)
 | 
			
		||||
  scope :closed, where(closed: true)
 | 
			
		||||
 | 
			
		||||
  validates :title, presence: true
 | 
			
		||||
  validates :project, presence: true
 | 
			
		||||
  validates :closed, inclusion: { in: [true, false] }
 | 
			
		||||
 | 
			
		||||
  def self.active
 | 
			
		||||
    where("due_date > ? OR due_date IS NULL", Date.today)
 | 
			
		||||
  def expired?
 | 
			
		||||
    if due_date
 | 
			
		||||
      due_date < Date.today
 | 
			
		||||
    else
 | 
			
		||||
      false
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def participants
 | 
			
		||||
| 
						 | 
				
			
			@ -52,4 +60,20 @@ class Milestone < ActiveRecord::Base
 | 
			
		|||
  def expires_at
 | 
			
		||||
    "expires at #{due_date.stamp("Aug 21, 2011")}" if due_date
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def can_be_closed?
 | 
			
		||||
    open? && issues.opened.count.zero?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def is_empty?
 | 
			
		||||
    total_items_count.zero?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def open?
 | 
			
		||||
    !closed
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def author_id
 | 
			
		||||
    author_id_of_changes
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,23 +48,30 @@ class Namespace < ActiveRecord::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def ensure_dir_exist
 | 
			
		||||
    namespace_dir_path = File.join(Gitlab.config.git_base_path, path)
 | 
			
		||||
    namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
 | 
			
		||||
    system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def move_dir
 | 
			
		||||
    if path_changed?
 | 
			
		||||
      old_path = File.join(Gitlab.config.git_base_path, path_was)
 | 
			
		||||
      new_path = File.join(Gitlab.config.git_base_path, path)
 | 
			
		||||
      old_path = File.join(Gitlab.config.gitolite.repos_path, path_was)
 | 
			
		||||
      new_path = File.join(Gitlab.config.gitolite.repos_path, path)
 | 
			
		||||
      if File.exists?(new_path)
 | 
			
		||||
        raise "Already exists"
 | 
			
		||||
      end
 | 
			
		||||
      system("mv #{old_path} #{new_path}")
 | 
			
		||||
 | 
			
		||||
      if system("mv #{old_path} #{new_path}")
 | 
			
		||||
        send_update_instructions
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def rm_dir
 | 
			
		||||
    dir_path = File.join(Gitlab.config.git_base_path, path)
 | 
			
		||||
    dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
 | 
			
		||||
    system("rm -rf #{dir_path}")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def send_update_instructions
 | 
			
		||||
    projects.each(&:send_move_instructions)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ require 'file_size_validator'
 | 
			
		|||
 | 
			
		||||
class Note < ActiveRecord::Base
 | 
			
		||||
  attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
 | 
			
		||||
                  :attachment, :line_code
 | 
			
		||||
                  :attachment, :line_code, :commit_id
 | 
			
		||||
 | 
			
		||||
  attr_accessor :notify
 | 
			
		||||
  attr_accessor :notify_author
 | 
			
		||||
| 
						 | 
				
			
			@ -35,10 +35,14 @@ class Note < ActiveRecord::Base
 | 
			
		|||
  validates :line_code, format: { with: /\A\d+_\d+_\d+\Z/ }, allow_blank: true
 | 
			
		||||
  validates :attachment, file_size: { maximum: 10.megabytes.to_i }
 | 
			
		||||
 | 
			
		||||
  validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
 | 
			
		||||
  validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
 | 
			
		||||
 | 
			
		||||
  mount_uploader :attachment, AttachmentUploader
 | 
			
		||||
 | 
			
		||||
  # Scopes
 | 
			
		||||
  scope :common, ->{ where(noteable_id: nil) }
 | 
			
		||||
  scope :for_commits, ->{ where(noteable_type: "Commit") }
 | 
			
		||||
  scope :common, ->{ where(noteable_id: nil, commit_id: nil) }
 | 
			
		||||
  scope :today, ->{ where("created_at >= :date", date: Date.today) }
 | 
			
		||||
  scope :last_week, ->{ where("created_at  >= :date", date: (Date.today - 7.days)) }
 | 
			
		||||
  scope :since, ->(day) { where("created_at  >= :date", date: (day)) }
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +126,7 @@ class Note < ActiveRecord::Base
 | 
			
		|||
  # override to return commits, which are not active record
 | 
			
		||||
  def noteable
 | 
			
		||||
    if for_commit?
 | 
			
		||||
      project.commit(noteable_id)
 | 
			
		||||
      project.commit(commit_id)
 | 
			
		||||
    else
 | 
			
		||||
      super
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -151,4 +155,12 @@ class Note < ActiveRecord::Base
 | 
			
		|||
  def votable?
 | 
			
		||||
    for_issue? || (for_merge_request? && !for_diff_line?)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def noteable_type_name
 | 
			
		||||
    if noteable_type.present?
 | 
			
		||||
      noteable_type.downcase
 | 
			
		||||
    else
 | 
			
		||||
      "wall"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,9 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  include PushObserver
 | 
			
		||||
  include Authority
 | 
			
		||||
  include Team
 | 
			
		||||
  include NamespacedProject
 | 
			
		||||
 | 
			
		||||
  class TransferError < StandardError; end
 | 
			
		||||
 | 
			
		||||
  attr_accessible :name, :path, :description, :default_branch, :issues_enabled,
 | 
			
		||||
                  :wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin]
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +39,10 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  # Relations
 | 
			
		||||
  belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
 | 
			
		||||
  belongs_to :namespace
 | 
			
		||||
 | 
			
		||||
  # TODO: replace owner with creator.
 | 
			
		||||
  # With namespaces a project owner will be a namespace owner
 | 
			
		||||
  # so this field makes sense only for global projects
 | 
			
		||||
  belongs_to :owner, class_name: "User"
 | 
			
		||||
  has_many :users,          through: :users_projects
 | 
			
		||||
  has_many :events,         dependent: :destroy
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +104,7 @@ class Project < ActiveRecord::Base
 | 
			
		|||
        namespace_id = Namespace.find_by_path(id.first).id
 | 
			
		||||
        where(namespace_id: namespace_id).find_by_path(id.last)
 | 
			
		||||
      else
 | 
			
		||||
        find_by_path(id)
 | 
			
		||||
        where(path: id, namespace_id: nil).last
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +179,7 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def repo_name
 | 
			
		||||
    denied_paths = %w(gitolite-admin groups projects dashboard)
 | 
			
		||||
    denied_paths = %w(gitolite-admin admin dashboard groups help profile projects search)
 | 
			
		||||
 | 
			
		||||
    if denied_paths.include?(path)
 | 
			
		||||
      errors.add(:path, "like #{path} is not allowed")
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +195,7 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def web_url
 | 
			
		||||
    [Gitlab.config.url, path].join("/")
 | 
			
		||||
    [Gitlab.config.gitlab.url, path_with_namespace].join("/")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def common_notes
 | 
			
		||||
| 
						 | 
				
			
			@ -196,15 +203,15 @@ class Project < ActiveRecord::Base
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def build_commit_note(commit)
 | 
			
		||||
    notes.new(noteable_id: commit.id, noteable_type: "Commit")
 | 
			
		||||
    notes.new(commit_id: commit.id, noteable_type: "Commit")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def commit_notes(commit)
 | 
			
		||||
    notes.where(noteable_id: commit.id, noteable_type: "Commit").where('line_code IS NULL OR line_code = ""')
 | 
			
		||||
    notes.where(commit_id: commit.id, noteable_type: "Commit").where('line_code IS NULL OR line_code = ""')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def commit_line_notes(commit)
 | 
			
		||||
    notes.where(noteable_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
 | 
			
		||||
    notes.where(commit_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def public?
 | 
			
		||||
| 
						 | 
				
			
			@ -239,51 +246,11 @@ class Project < ActiveRecord::Base
 | 
			
		|||
    gitlab_ci_service && gitlab_ci_service.active
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def path_with_namespace
 | 
			
		||||
    if namespace
 | 
			
		||||
      namespace.path + '/' + path
 | 
			
		||||
    else
 | 
			
		||||
      path
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # For compatibility with old code
 | 
			
		||||
  def code
 | 
			
		||||
    path
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def transfer(new_namespace)
 | 
			
		||||
    Project.transaction do
 | 
			
		||||
      old_namespace = namespace
 | 
			
		||||
      self.namespace = new_namespace
 | 
			
		||||
 | 
			
		||||
      old_dir = old_namespace.try(:path) || ''
 | 
			
		||||
      new_dir = new_namespace.try(:path) || ''
 | 
			
		||||
 | 
			
		||||
      old_repo = if old_dir.present?
 | 
			
		||||
                   File.join(old_dir, self.path)
 | 
			
		||||
                 else
 | 
			
		||||
                   self.path
 | 
			
		||||
                 end
 | 
			
		||||
 | 
			
		||||
      Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
 | 
			
		||||
 | 
			
		||||
      git_host.move_repository(old_repo, self)
 | 
			
		||||
 | 
			
		||||
      save!
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def name_with_namespace
 | 
			
		||||
    @name_with_namespace ||= begin
 | 
			
		||||
                               if namespace
 | 
			
		||||
                                 namespace.human_name + " / " + name
 | 
			
		||||
                               else
 | 
			
		||||
                                 name
 | 
			
		||||
                               end
 | 
			
		||||
                             end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def items_for entity
 | 
			
		||||
    case entity
 | 
			
		||||
    when 'issue' then
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +260,9 @@ class Project < ActiveRecord::Base
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def namespace_owner
 | 
			
		||||
    namespace.try(:owner)
 | 
			
		||||
  def send_move_instructions
 | 
			
		||||
    self.users_projects.each do |member|
 | 
			
		||||
      Notify.project_was_moved_email(member.id).deliver
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ class Snippet < ActiveRecord::Base
 | 
			
		|||
  belongs_to :author, class_name: "User"
 | 
			
		||||
  has_many :notes, as: :noteable, dependent: :destroy
 | 
			
		||||
 | 
			
		||||
  delegate :name, :email, to: :author, prefix: true
 | 
			
		||||
  delegate :name, :email, to: :author, prefix: true, allow_nil: true
 | 
			
		||||
 | 
			
		||||
  validates :author, presence: true
 | 
			
		||||
  validates :project, presence: true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,12 +56,12 @@ class User < ActiveRecord::Base
 | 
			
		|||
  has_many :issues, foreign_key: :author_id, dependent: :destroy
 | 
			
		||||
  has_many :notes, foreign_key: :author_id, dependent: :destroy
 | 
			
		||||
  has_many :merge_requests, foreign_key: :author_id, dependent: :destroy
 | 
			
		||||
  has_many :my_own_projects, class_name: "Project", foreign_key: :owner_id
 | 
			
		||||
  has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy
 | 
			
		||||
  has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
 | 
			
		||||
  has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
 | 
			
		||||
  has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy
 | 
			
		||||
 | 
			
		||||
  validates :name, presence: true
 | 
			
		||||
  validates :bio, length: { within: 0..255 }
 | 
			
		||||
  validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
 | 
			
		||||
  validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
 | 
			
		||||
| 
						 | 
				
			
			@ -123,16 +123,4 @@ class User < ActiveRecord::Base
 | 
			
		|||
      self.password = self.password_confirmation = Devise.friendly_token.first(8)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorized_groups
 | 
			
		||||
    @authorized_groups ||= begin
 | 
			
		||||
                           groups = Group.where(id: self.projects.pluck(:namespace_id)).all
 | 
			
		||||
                           groups = groups + self.groups
 | 
			
		||||
                           groups.uniq
 | 
			
		||||
                         end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorized_projects
 | 
			
		||||
    Project.authorized_for(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ class UsersProject < ActiveRecord::Base
 | 
			
		|||
 | 
			
		||||
  validates :user, presence: true
 | 
			
		||||
  validates :user_id, uniqueness: { :scope => [:project_id], message: "already exists in project" }
 | 
			
		||||
  validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
 | 
			
		||||
  validates :project, presence: true
 | 
			
		||||
 | 
			
		||||
  delegate :name, :email, to: :user, prefix: true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,27 @@
 | 
			
		|||
class ActivityObserver < ActiveRecord::Observer
 | 
			
		||||
  observe :issue, :merge_request
 | 
			
		||||
  observe :issue, :merge_request, :note, :milestone
 | 
			
		||||
 | 
			
		||||
  def after_create(record)
 | 
			
		||||
    event_author_id = record.author_id
 | 
			
		||||
 | 
			
		||||
    # Skip status notes
 | 
			
		||||
    if record.kind_of?(Note) && record.note.include?("_Status changed to ")
 | 
			
		||||
      return true
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if event_author_id
 | 
			
		||||
      Event.create(
 | 
			
		||||
        project: record.project,
 | 
			
		||||
        target_id: record.id,
 | 
			
		||||
        target_type: record.class.name,
 | 
			
		||||
        action: Event.determine_action(record),
 | 
			
		||||
      author_id: record.author_id
 | 
			
		||||
        author_id: event_author_id
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def after_save(record)
 | 
			
		||||
    if record.changed.include?("closed") 
 | 
			
		||||
    if record.changed.include?("closed") && record.author_id_of_changes
 | 
			
		||||
      Event.create(
 | 
			
		||||
        project: record.project,
 | 
			
		||||
        target_id: record.id,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ class IssueObserver < ActiveRecord::Observer
 | 
			
		|||
    if status
 | 
			
		||||
      Note.create_status_change_note(issue, current_user, status)
 | 
			
		||||
      [issue.author, issue.assignee].compact.each do |recipient|
 | 
			
		||||
        Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user)
 | 
			
		||||
        Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user.id).deliver
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ class NoteObserver < ActiveRecord::Observer
 | 
			
		|||
  # Notifies the whole team except the author of note
 | 
			
		||||
  def notify_team(note)
 | 
			
		||||
    # Note: wall posts are not "attached" to anything, so fall back to "Wall"
 | 
			
		||||
    noteable_type = note.noteable_type || "Wall"
 | 
			
		||||
    noteable_type = note.noteable_type.presence || "Wall"
 | 
			
		||||
    notify_method = "note_#{noteable_type.underscore}_email".to_sym
 | 
			
		||||
 | 
			
		||||
    if Notify.respond_to? notify_method
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,8 @@ class ProjectObserver < ActiveRecord::Observer
 | 
			
		|||
    project.update_repository
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def after_save(project)
 | 
			
		||||
  def after_update(project)
 | 
			
		||||
    project.send_move_instructions if project.namespace_id_changed?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def after_destroy(project)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ module Account
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def cared_merge_requests
 | 
			
		||||
    MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id).opened
 | 
			
		||||
    MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def project_ids
 | 
			
		||||
| 
						 | 
				
			
			@ -105,4 +105,20 @@ module Account
 | 
			
		|||
  def namespace_id
 | 
			
		||||
    namespace.try :id
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorized_groups
 | 
			
		||||
    @authorized_groups ||= begin
 | 
			
		||||
                           groups = Group.where(id: self.projects.pluck(:namespace_id)).all
 | 
			
		||||
                           groups = groups + self.groups
 | 
			
		||||
                           groups.uniq
 | 
			
		||||
                         end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def authorized_projects
 | 
			
		||||
    Project.authorized_for(self)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def my_own_projects
 | 
			
		||||
    Project.personal(self)
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
module NamespacedProject
 | 
			
		||||
  def transfer(new_namespace)
 | 
			
		||||
    Project.transaction do
 | 
			
		||||
      old_namespace = namespace
 | 
			
		||||
      self.namespace = new_namespace
 | 
			
		||||
 | 
			
		||||
      old_dir = old_namespace.try(:path) || ''
 | 
			
		||||
      new_dir = new_namespace.try(:path) || ''
 | 
			
		||||
 | 
			
		||||
      old_repo = if old_dir.present?
 | 
			
		||||
                   File.join(old_dir, self.path)
 | 
			
		||||
                 else
 | 
			
		||||
                   self.path
 | 
			
		||||
                 end
 | 
			
		||||
 | 
			
		||||
      if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
 | 
			
		||||
        raise TransferError.new("Project with same path in target namespace already exists")
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
 | 
			
		||||
 | 
			
		||||
      git_host.move_repository(old_repo, self)
 | 
			
		||||
 | 
			
		||||
      save!
 | 
			
		||||
    end
 | 
			
		||||
  rescue Gitlab::ProjectMover::ProjectMoveError => ex
 | 
			
		||||
    raise TransferError.new(ex.message)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def name_with_namespace
 | 
			
		||||
    @name_with_namespace ||= begin
 | 
			
		||||
                               if namespace
 | 
			
		||||
                                 namespace.human_name + " / " + name
 | 
			
		||||
                               else
 | 
			
		||||
                                 name
 | 
			
		||||
                               end
 | 
			
		||||
                             end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def namespace_owner
 | 
			
		||||
    namespace.try(:owner)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def chief
 | 
			
		||||
    if namespace
 | 
			
		||||
      namespace_owner
 | 
			
		||||
    else
 | 
			
		||||
      owner
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def path_with_namespace
 | 
			
		||||
    if namespace
 | 
			
		||||
      namespace.path + '/' + path
 | 
			
		||||
    else
 | 
			
		||||
      path
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
module NoteEvent
 | 
			
		||||
  def note_commit_id
 | 
			
		||||
    target.commit_id
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note_short_commit_id
 | 
			
		||||
    note_commit_id[0..8]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note_commit?
 | 
			
		||||
    target.noteable_type == "Commit"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note_target
 | 
			
		||||
    target.noteable
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note_target_id
 | 
			
		||||
    if note_commit?
 | 
			
		||||
      target.commit_id
 | 
			
		||||
    else
 | 
			
		||||
      target.noteable_id.to_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def wall_note?
 | 
			
		||||
    target.noteable_type.blank?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def note_target_type
 | 
			
		||||
    if target.noteable_type.present?
 | 
			
		||||
      target.noteable_type.titleize
 | 
			
		||||
    else
 | 
			
		||||
      "Wall"
 | 
			
		||||
    end.downcase
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ module PushObserver
 | 
			
		|||
        id: commit.id,
 | 
			
		||||
        message: commit.safe_message,
 | 
			
		||||
        timestamp: commit.date.xmlschema,
 | 
			
		||||
        url: "#{Gitlab.config.url}/#{path}/commits/#{commit.id}",
 | 
			
		||||
        url: "#{Gitlab.config.gitlab.url}/#{path_with_namespace}/commit/#{commit.id}",
 | 
			
		||||
        author: {
 | 
			
		||||
          name: commit.author_name,
 | 
			
		||||
          email: commit.author_email
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,8 +45,22 @@ module Repository
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def has_post_receive_file?
 | 
			
		||||
    hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
 | 
			
		||||
    File.exists?(hook_file)
 | 
			
		||||
    !!hook_file
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def valid_post_receive_file?
 | 
			
		||||
    valid_hook_file == hook_file
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def valid_hook_file
 | 
			
		||||
    @valid_hook_file ||= File.read(Rails.root.join('lib', 'hooks', 'post-receive'))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def hook_file
 | 
			
		||||
    @hook_file ||= begin
 | 
			
		||||
                     hook_path = File.join(path_to_repo, 'hooks', 'post-receive')
 | 
			
		||||
                     File.read(hook_path) if File.exists?(hook_path)
 | 
			
		||||
                   end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Returns an Array of branch names
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +97,7 @@ module Repository
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def path_to_repo
 | 
			
		||||
    File.join(Gitlab.config.git_base_path, "#{path_with_namespace}.git")
 | 
			
		||||
    File.join(Gitlab.config.gitolite.repos_path, "#{path_with_namespace}.git")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def namespace_dir
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +199,7 @@ module Repository
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def http_url_to_repo
 | 
			
		||||
    http_url = [Gitlab.config.url, "/", path_with_namespace, ".git"].join('')
 | 
			
		||||
    http_url = [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Check if current branch name is marked as protected in the system
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
= form_for [:admin, @group] do |f|
 | 
			
		||||
  - if @group.errors.any?
 | 
			
		||||
    .alert-message.block-message.error
 | 
			
		||||
      %span= @group.errors.full_messages.first
 | 
			
		||||
  .clearfix.group_name_holder
 | 
			
		||||
    = f.label :name do
 | 
			
		||||
      Group name is
 | 
			
		||||
    .input
 | 
			
		||||
      = f.text_field :name, placeholder: "Example Group", class: "xxlarge"
 | 
			
		||||
 | 
			
		||||
  .form-actions
 | 
			
		||||
    = f.submit 'Save group', class: "btn save-btn"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,28 @@
 | 
			
		|||
%h3.page_title Edit Group
 | 
			
		||||
%br
 | 
			
		||||
= render 'form'
 | 
			
		||||
%h3.page_title Rename Group
 | 
			
		||||
%hr
 | 
			
		||||
= form_for [:admin, @group] do |f|
 | 
			
		||||
  - if @group.errors.any?
 | 
			
		||||
    .alert-message.block-message.error
 | 
			
		||||
      %span= @group.errors.full_messages.first
 | 
			
		||||
  .clearfix.group_name_holder
 | 
			
		||||
    = f.label :name do
 | 
			
		||||
      Group name is
 | 
			
		||||
    .input
 | 
			
		||||
      = f.text_field :name, placeholder: "Example Group", class: "xxlarge"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  .clearfix.group_name_holder
 | 
			
		||||
    = f.label :path do
 | 
			
		||||
      %span.cred Group path is
 | 
			
		||||
    .input
 | 
			
		||||
      = f.text_field :path, placeholder: "example-group", class: "xxlarge danger"
 | 
			
		||||
      %ul.cred
 | 
			
		||||
        %li Changing group path can have unintended side effects.
 | 
			
		||||
        %li Renaming group path will rename directory for all related projects
 | 
			
		||||
        %li It will change web url for access group and group projects.
 | 
			
		||||
        %li It will change the git path to repositories under this group.
 | 
			
		||||
 | 
			
		||||
  .form-actions
 | 
			
		||||
    = f.submit 'Rename group', class: "btn danger"
 | 
			
		||||
    = link_to  'Cancel', admin_groups_path, class: "btn cancel-btn"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,17 +12,24 @@
 | 
			
		|||
 | 
			
		||||
%table
 | 
			
		||||
  %thead
 | 
			
		||||
    %th Name
 | 
			
		||||
    %tr
 | 
			
		||||
      %th
 | 
			
		||||
        Name
 | 
			
		||||
        %i.icon-sort-down
 | 
			
		||||
      %th Path
 | 
			
		||||
      %th Projects
 | 
			
		||||
    %th Edit
 | 
			
		||||
      %th Owner
 | 
			
		||||
      %th.cred Danger Zone!
 | 
			
		||||
 | 
			
		||||
  - @groups.each do |group|
 | 
			
		||||
    %tr
 | 
			
		||||
      %td= link_to group.name, [:admin, group]
 | 
			
		||||
      %td
 | 
			
		||||
        %strong= link_to group.name, [:admin, group]
 | 
			
		||||
      %td= group.path
 | 
			
		||||
      %td= group.projects.count
 | 
			
		||||
      %td= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
 | 
			
		||||
      %td.bgred= link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small danger"
 | 
			
		||||
      %td
 | 
			
		||||
        = link_to group.owner_name, admin_user_path(group.owner_id)
 | 
			
		||||
      %td.bgred
 | 
			
		||||
        = link_to 'Rename', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: "btn small"
 | 
			
		||||
        = link_to 'Destroy', [:admin, group], confirm: "REMOVE #{group.name}? Are you sure?", method: :delete, class: "btn small danger"
 | 
			
		||||
= paginate @groups, theme: "admin"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,5 @@
 | 
			
		|||
%h3.page_title
 | 
			
		||||
  Group: #{@group.name}
 | 
			
		||||
  = link_to edit_admin_group_path(@group), class: "btn right" do
 | 
			
		||||
    %i.icon-edit
 | 
			
		||||
    Edit
 | 
			
		||||
 | 
			
		||||
%br
 | 
			
		||||
%table.zebra-striped
 | 
			
		||||
| 
						 | 
				
			
			@ -16,36 +13,64 @@
 | 
			
		|||
        Name:
 | 
			
		||||
    %td
 | 
			
		||||
      = @group.name
 | 
			
		||||
       
 | 
			
		||||
      = link_to edit_admin_group_path(@group), class: "btn btn-small right" do
 | 
			
		||||
        %i.icon-edit
 | 
			
		||||
        Rename
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Path:
 | 
			
		||||
    %td
 | 
			
		||||
      %span.monospace= File.join(Gitlab.config.git_base_path, @group.path)
 | 
			
		||||
      %span.monospace= File.join(Gitlab.config.gitolite.repos_path, @group.path)
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Owner:
 | 
			
		||||
    %td
 | 
			
		||||
      = @group.owner_name
 | 
			
		||||
.ui-box
 | 
			
		||||
  %h5
 | 
			
		||||
    Projects
 | 
			
		||||
    %small
 | 
			
		||||
      (#{@group.projects.count})
 | 
			
		||||
  %ul.unstyled
 | 
			
		||||
    - @group.projects.each do |project|
 | 
			
		||||
      %li.wll
 | 
			
		||||
        %strong
 | 
			
		||||
          = link_to project.name, [:admin, project]
 | 
			
		||||
      .right
 | 
			
		||||
          = link_to 'Remove from group', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
 | 
			
		||||
        .clearfix
 | 
			
		||||
        = link_to "#", class: "btn btn-small change-owner-link" do
 | 
			
		||||
          %i.icon-edit
 | 
			
		||||
          Change owner
 | 
			
		||||
 | 
			
		||||
  %tr.change-owner-holder.hide
 | 
			
		||||
    %td.bgred
 | 
			
		||||
      %b.cred
 | 
			
		||||
        New Owner:
 | 
			
		||||
    %td.bgred
 | 
			
		||||
      = form_for [:admin, @group] do |f|
 | 
			
		||||
        = f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
 | 
			
		||||
        %div
 | 
			
		||||
          = f.submit 'Change Owner', class: "btn danger"
 | 
			
		||||
          = link_to "Cancel", "#", class: "btn change-owner-cancel-link"
 | 
			
		||||
%fieldset
 | 
			
		||||
  %legend Projects (#{@group.projects.count})
 | 
			
		||||
  %table
 | 
			
		||||
    %thead
 | 
			
		||||
      %tr
 | 
			
		||||
        %th Project name
 | 
			
		||||
        %th Path
 | 
			
		||||
        %th Users
 | 
			
		||||
        %th.cred Danger Zone!
 | 
			
		||||
    - @group.projects.each do |project|
 | 
			
		||||
      %tr
 | 
			
		||||
        %td
 | 
			
		||||
          = link_to project.name_with_namespace, [:admin, project]
 | 
			
		||||
        %td
 | 
			
		||||
          %span.monospace= project.path_with_namespace + ".git"
 | 
			
		||||
        %td= project.users.count
 | 
			
		||||
        %td.bgred
 | 
			
		||||
          = link_to 'Transfer project to global namespace', remove_project_admin_group_path(@group, project_id: project.id), confirm: 'Remove project from group and move to global namespace. Are you sure?', method: :delete, class: "btn danger small"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
= form_tag project_update_admin_group_path(@group), class: "bulk_import", method: :put  do
 | 
			
		||||
  %fieldset
 | 
			
		||||
    %legend Move projects to group
 | 
			
		||||
    .alert
 | 
			
		||||
      You can move only projects with existing repos
 | 
			
		||||
      %br
 | 
			
		||||
      Group projects will be moved in group directory and will not be accessible by old path
 | 
			
		||||
    .clearfix
 | 
			
		||||
      = label_tag :project_ids do
 | 
			
		||||
        Projects
 | 
			
		||||
| 
						 | 
				
			
			@ -53,3 +78,17 @@
 | 
			
		|||
        = select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
 | 
			
		||||
    .form-actions
 | 
			
		||||
      = submit_tag 'Add', class: "btn primary"
 | 
			
		||||
 | 
			
		||||
:javascript
 | 
			
		||||
  $(function(){
 | 
			
		||||
    var modal = $('.change-owner-holder');
 | 
			
		||||
    $('.change-owner-link').bind("click", function(){
 | 
			
		||||
      $(this).hide();
 | 
			
		||||
      modal.show();
 | 
			
		||||
    });
 | 
			
		||||
    $('.change-owner-cancel-link').bind("click", function(){
 | 
			
		||||
      modal.hide();
 | 
			
		||||
      $('.change-owner-link').show();
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@
 | 
			
		|||
    = link_to "githost.log", "#githost", 'data-toggle' => 'tab'
 | 
			
		||||
  %li
 | 
			
		||||
    = link_to "application.log", "#application", 'data-toggle' => 'tab'
 | 
			
		||||
  %li
 | 
			
		||||
    = link_to "production.log", "#production", 'data-toggle' => 'tab'
 | 
			
		||||
 | 
			
		||||
%p.light To prevent perfomance issues admin logs output the last 2000 lines
 | 
			
		||||
.tab-content
 | 
			
		||||
| 
						 | 
				
			
			@ -34,3 +36,17 @@
 | 
			
		|||
          - Gitlab::AppLogger.read_latest.each do |line|
 | 
			
		||||
            %li
 | 
			
		||||
              %p= line
 | 
			
		||||
  .tab-pane#production
 | 
			
		||||
    .file_holder#README
 | 
			
		||||
      .file_title
 | 
			
		||||
        %i.icon-file
 | 
			
		||||
        production.log
 | 
			
		||||
        .right
 | 
			
		||||
          = link_to '#', class: 'log-bottom' do
 | 
			
		||||
            %i.icon-arrow-down
 | 
			
		||||
            Scroll down
 | 
			
		||||
      .file_content.logs
 | 
			
		||||
        %ol
 | 
			
		||||
          - Gitlab::Logger.read_latest_for('production.log').each do |line|
 | 
			
		||||
            %li
 | 
			
		||||
              %p= line
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,17 +19,11 @@
 | 
			
		|||
      .input
 | 
			
		||||
        = text_field_tag :ppath, @project.path_to_repo, class: "xlarge", disabled: true
 | 
			
		||||
 | 
			
		||||
    - unless project.new_record?
 | 
			
		||||
      .clearfix
 | 
			
		||||
        = f.label :namespace_id
 | 
			
		||||
        .input= f.select :namespace_id, namespaces_options(@project.namespace_id), {}, {class: 'chosen'}
 | 
			
		||||
 | 
			
		||||
    - if project.repo_exists?
 | 
			
		||||
      .clearfix
 | 
			
		||||
        = f.label :default_branch, "Default Branch"
 | 
			
		||||
        .input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
 | 
			
		||||
 | 
			
		||||
  - unless project.new_record?
 | 
			
		||||
  %fieldset.adv_settings
 | 
			
		||||
    %legend Features:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +43,20 @@
 | 
			
		|||
      = f.label :wiki_enabled, "Wiki"
 | 
			
		||||
      .input= f.check_box :wiki_enabled
 | 
			
		||||
 | 
			
		||||
  - unless project.new_record?
 | 
			
		||||
  %fieldset.features
 | 
			
		||||
    %legend Transfer:
 | 
			
		||||
    .control-group
 | 
			
		||||
      = f.label :namespace_id do
 | 
			
		||||
        %span Namespace
 | 
			
		||||
      .controls
 | 
			
		||||
        = f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'}
 | 
			
		||||
        %br
 | 
			
		||||
        %ul.prepend-top-10.cred
 | 
			
		||||
          %li Be careful. Changing project namespace can have unintended side effects
 | 
			
		||||
          %li You can transfer project only to namespaces you can manage
 | 
			
		||||
          %li You will need to update your local repositories to point to the new location.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  .actions
 | 
			
		||||
    = f.submit 'Save Project', class: "btn save-btn"
 | 
			
		||||
    = link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
%h3.page_title
 | 
			
		||||
  Projects
 | 
			
		||||
  Projects (#{@projects.count})
 | 
			
		||||
  = link_to 'New Project', new_project_path, class: "btn small right"
 | 
			
		||||
%br
 | 
			
		||||
= form_tag admin_projects_path, method: :get, class: 'form-inline' do
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,10 @@
 | 
			
		|||
 | 
			
		||||
%table
 | 
			
		||||
  %thead
 | 
			
		||||
    %th Name
 | 
			
		||||
    %tr
 | 
			
		||||
      %th
 | 
			
		||||
        Name
 | 
			
		||||
        %i.icon-sort-down
 | 
			
		||||
      %th Path
 | 
			
		||||
      %th Team Members
 | 
			
		||||
      %th Last Commit
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,14 +4,24 @@
 | 
			
		|||
    %i.icon-edit
 | 
			
		||||
    Edit
 | 
			
		||||
 | 
			
		||||
- if !@project.has_post_receive_file? && @project.has_commits?
 | 
			
		||||
- if @project.has_commits?
 | 
			
		||||
  - if !@project.has_post_receive_file?
 | 
			
		||||
    %br
 | 
			
		||||
    .alert.alert-error
 | 
			
		||||
      %span
 | 
			
		||||
      %strong Important!
 | 
			
		||||
      Project has commits but missing post-receive file.
 | 
			
		||||
        %strong Project has commits but missing post-receive file.
 | 
			
		||||
        %br
 | 
			
		||||
      If you exported project manually - copy post-receive hook to bare repository
 | 
			
		||||
        If you exported project manually - make a link of post-receive hook file from gitolite to project repository
 | 
			
		||||
  - elsif !@project.valid_post_receive_file?
 | 
			
		||||
    %br
 | 
			
		||||
    .alert.alert-error
 | 
			
		||||
      %span
 | 
			
		||||
        %strong Project has invalid post-receive file.
 | 
			
		||||
        %br
 | 
			
		||||
        1. Make sure your gitolite instace has latest post-receive file.
 | 
			
		||||
        %br
 | 
			
		||||
        2. Make a link of post-receive hook file from gitolite to project repository
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
%br
 | 
			
		||||
%table.zebra-striped
 | 
			
		||||
| 
						 | 
				
			
			@ -37,23 +47,63 @@
 | 
			
		|||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Path:
 | 
			
		||||
        Owned by:
 | 
			
		||||
    %td
 | 
			
		||||
      %code= @project.path_to_repo
 | 
			
		||||
      - if @project.chief
 | 
			
		||||
        = link_to @project.chief.name, admin_user_path(@project.chief)
 | 
			
		||||
      - else
 | 
			
		||||
        (deleted)
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Created by:
 | 
			
		||||
    %td
 | 
			
		||||
      = @project.owner_name || '(deleted)'
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Created at:
 | 
			
		||||
    %td
 | 
			
		||||
      = @project.created_at.stamp("March 1, 1999")
 | 
			
		||||
 | 
			
		||||
%table.zebra-striped
 | 
			
		||||
  %thead
 | 
			
		||||
    %tr
 | 
			
		||||
      %th Repository
 | 
			
		||||
      %th
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        FS Path:
 | 
			
		||||
    %td
 | 
			
		||||
      %code= @project.path_to_repo
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Smart HTTP:
 | 
			
		||||
    %td
 | 
			
		||||
      = link_to @project.http_url_to_repo
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        SSH:
 | 
			
		||||
    %td
 | 
			
		||||
      = link_to @project.ssh_url_to_repo
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Last commit at:
 | 
			
		||||
    %td
 | 
			
		||||
      = last_commit(@project)
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Post Receive File:
 | 
			
		||||
    %td
 | 
			
		||||
      = check_box_tag :post_receive_file, 1, @project.has_post_receive_file?, disabled: true
 | 
			
		||||
 | 
			
		||||
%br
 | 
			
		||||
%h3
 | 
			
		||||
%h5
 | 
			
		||||
  Team
 | 
			
		||||
  %small
 | 
			
		||||
    (#{@project.users_projects.count})
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +125,7 @@
 | 
			
		|||
      %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn danger small"
 | 
			
		||||
 | 
			
		||||
%br
 | 
			
		||||
%h3 Add new team member
 | 
			
		||||
%h5 Add new team member
 | 
			
		||||
%br
 | 
			
		||||
= form_tag team_update_admin_project_path(@project), class: "bulk_import", method: :put  do
 | 
			
		||||
  %table.zebra-striped
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
%h3.page_title
 | 
			
		||||
  Users
 | 
			
		||||
  Users (#{@admin_users.count})
 | 
			
		||||
  = link_to 'New User', new_admin_user_path, class: "btn small right"
 | 
			
		||||
%br
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,8 +21,11 @@
 | 
			
		|||
 | 
			
		||||
%table
 | 
			
		||||
  %thead
 | 
			
		||||
    %tr
 | 
			
		||||
      %th Admin
 | 
			
		||||
    %th Name
 | 
			
		||||
      %th
 | 
			
		||||
        Name
 | 
			
		||||
        %i.icon-sort-down
 | 
			
		||||
      %th Username
 | 
			
		||||
      %th Email
 | 
			
		||||
      %th Projects
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +41,9 @@
 | 
			
		|||
      %td= user.users_projects.count
 | 
			
		||||
      %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
 | 
			
		||||
      %td.bgred
 | 
			
		||||
        - if user == current_user
 | 
			
		||||
          %span.cred It's you!
 | 
			
		||||
        - else
 | 
			
		||||
          - if user.blocked
 | 
			
		||||
            = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
 | 
			
		||||
          - else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,12 @@
 | 
			
		|||
      %b
 | 
			
		||||
        Blocked:
 | 
			
		||||
        %td= check_box_tag "blocked", 1, @admin_user.blocked, disabled: :disabled
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
        Created at:
 | 
			
		||||
    %td
 | 
			
		||||
      = @admin_user.created_at.stamp("March 1, 1999")
 | 
			
		||||
  %tr
 | 
			
		||||
    %td
 | 
			
		||||
      %b
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +72,7 @@
 | 
			
		|||
        = @admin_user.twitter
 | 
			
		||||
 | 
			
		||||
%br
 | 
			
		||||
%h3 Add User to Projects
 | 
			
		||||
%h5 Add User to Projects
 | 
			
		||||
%br
 | 
			
		||||
= form_tag team_update_admin_user_path(@admin_user), class: "bulk_import", method: :put  do
 | 
			
		||||
  %table
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +82,7 @@
 | 
			
		|||
        %th Project Access:
 | 
			
		||||
 | 
			
		||||
    %tr
 | 
			
		||||
      %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name),  multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
 | 
			
		||||
      %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name_with_namespace),  multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
 | 
			
		||||
      %td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
 | 
			
		||||
 | 
			
		||||
    %tr
 | 
			
		||||
| 
						 | 
				
			
			@ -86,8 +92,22 @@
 | 
			
		|||
        %strong= link_to "here", help_permissions_path, class: "vlink"
 | 
			
		||||
%br
 | 
			
		||||
 | 
			
		||||
- if @admin_user.groups.present?
 | 
			
		||||
  %h5 Owner of groups:
 | 
			
		||||
  %br
 | 
			
		||||
 | 
			
		||||
  %table.zebra-striped
 | 
			
		||||
    %thead
 | 
			
		||||
      %tr
 | 
			
		||||
        %th Name
 | 
			
		||||
 | 
			
		||||
    - @admin_user.groups.each do |group|
 | 
			
		||||
      %tr
 | 
			
		||||
        %td= link_to group.name, admin_group_path(group)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
- if @admin_user.projects.present?
 | 
			
		||||
  %h3 Projects
 | 
			
		||||
  %h5 Projects:
 | 
			
		||||
  %br
 | 
			
		||||
 | 
			
		||||
  %table.zebra-striped
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +121,7 @@
 | 
			
		|||
    - @admin_user.users_projects.each do |tm|
 | 
			
		||||
      - project = tm.project
 | 
			
		||||
      %tr
 | 
			
		||||
        %td= link_to project.name, admin_project_path(project)
 | 
			
		||||
        %td= link_to project.name_with_namespace, admin_project_path(project)
 | 
			
		||||
        %td= tm.project_access_human
 | 
			
		||||
        %td= link_to 'Edit Access', edit_admin_team_member_path(tm), class: "btn small"
 | 
			
		||||
        %td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,4 +3,4 @@
 | 
			
		|||
    %h5.small
 | 
			
		||||
      %i.icon-calendar
 | 
			
		||||
      = day.stamp("28 Aug, 2010")
 | 
			
		||||
    %ul.unstyled= render commits
 | 
			
		||||
    %ul.well-list= render commits
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
%div
 | 
			
		||||
  - unless params[:to]
 | 
			
		||||
    %p.slead
 | 
			
		||||
      Fill input field with commit id like
 | 
			
		||||
      %code.label_branch 4eedf23
 | 
			
		||||
| 
						 | 
				
			
			@ -10,14 +11,20 @@
 | 
			
		|||
 | 
			
		||||
  = form_tag project_compare_index_path(@project), method: :post do
 | 
			
		||||
    .clearfix
 | 
			
		||||
      .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 :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
 | 
			
		||||
      .pull-left
 | 
			
		||||
         
 | 
			
		||||
        = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
 | 
			
		||||
    - if @refs_are_same
 | 
			
		||||
      .alert
 | 
			
		||||
        %span Refs are the same
 | 
			
		||||
    .actions
 | 
			
		||||
      = submit_tag "Compare", class: "btn primary wide commits-compare-btn"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
:javascript
 | 
			
		||||
  $(function() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@
 | 
			
		|||
- if @commits.present?
 | 
			
		||||
  %div.ui-box
 | 
			
		||||
    %h5.small Commits (#{@commits.count})
 | 
			
		||||
    %ul.unstyled= render @commits
 | 
			
		||||
    %ul.well-list= render @commits
 | 
			
		||||
 | 
			
		||||
  - unless @diffs.empty?
 | 
			
		||||
    %h4 Diff
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||