diff --git a/.travis.yml b/.travis.yml
index df3974fe..fe602a59 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ env:
before_install:
- sudo apt-get install libicu-dev -y
- sudo apt-get install libqt4-dev libqtwebkit-dev -y
- - gem install charlock_holmes -v="0.6.8"
+ - gem install charlock_holmes -v="0.6.9"
branches:
only:
- 'master'
diff --git a/CHANGELOG b/CHANGELOG
index a4debcc4..58111484 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,7 +28,7 @@ v 3.0.0
- Reject ssh keys that break gitolite
- [API] list one project hook
- [API] edit project hook
- - [API] add project snippets list
+ - [API] list project snippets
- [API] allow to authorize using private token in HTTP header
- [API] add user creation
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4b87ac4c..5f831446 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-## Contribute to GitLab
+## Contribute to GitLab
If you want to contribute to GitLab, follow this process:
@@ -7,24 +7,20 @@ If you want to contribute to GitLab, follow this process:
3. Code
4. Create a pull request
-We will only accept pull requests if:
+We will only accept pull requests if:
* Your code has proper tests and all tests pass
-* Your code can be merged w/o problems
+* Your code can be merged w/o problems
* It won't break existing functionality
* It's quality code
* We like it :)
-## [You may need a developer VM](https://github.com/gitlabhq/developer-vm)
+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).
+
+## Installation
+
+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.
## Running tests
-To run the specs for GitLab, you need to run seeds for test db.
-
- cd gitlabhq
- rake db:seed_fu RAILS_ENV=test
-
-Then you can run the test suite with rake:
-
- rake gitlab:test
-
+For more information on running the tests please read the [development tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
diff --git a/Gemfile b/Gemfile
index 65c69e7e..84b557ba 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,9 +11,9 @@ end
gem "rails", "3.2.8"
# Supported DBs
-gem "sqlite3", :group => :sqlite
-gem "mysql2", :group => :mysql
-gem "pg", :group => :postgres
+gem "sqlite3", group: :sqlite
+gem "mysql2", group: :mysql
+gem "pg", group: :postgres
# Auth
gem "devise", "~> 2.1.0"
@@ -23,10 +23,11 @@ gem 'omniauth-twitter'
gem 'omniauth-github'
# GITLAB patched libs
-gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
-gem "omniauth-ldap", :git => "https://github.com/gitlabhq/omniauth-ldap.git", :ref => "f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e"
-gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git"
-gem 'grack', :git => "https://github.com/gitlabhq/grack.git"
+gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '7f35cb98ff17d534a07e3ce6ec3d580f67402837'
+gem "omniauth-ldap", git: "https://github.com/gitlabhq/omniauth-ldap.git", ref: 'f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e'
+gem 'yaml_db', git: "https://github.com/gitlabhq/yaml_db.git", ref: '98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd'
+gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'
+gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '212fd40bea61f3c6a167223768e7295dc32bbc10'
# Gitolite client (for work with gitolite-admin repo)
gem "gitolite", '1.1.0'
@@ -35,7 +36,7 @@ gem "gitolite", '1.1.0'
gem "pygments.rb", "0.3.1"
# Language detection
-gem "github-linguist", "~> 2.3.4" , :require => "linguist"
+gem "github-linguist", "~> 2.3.4" , require: "linguist"
# API
gem "grape", "~> 0.2.1"
@@ -83,9 +84,6 @@ gem 'resque_mailer'
# HTTP requests
gem "httparty"
-# Handle encodings
-gem "charlock_holmes"
-
# Colored output to console
gem "colored"
@@ -114,8 +112,9 @@ group :assets do
end
group :development do
+ gem "annotate", git: "https://github.com/ctran/annotate_models.git"
gem "letter_opener"
- gem "annotate", :git => "https://github.com/ctran/annotate_models.git"
+ gem 'quiet_assets', '1.0.1'
gem 'rack-mini-profiler'
end
@@ -137,13 +136,13 @@ group :development, :test do
gem 'guard-spinach'
# Notification
- gem 'rb-fsevent', :require => darwin_only('rb-fsevent')
- gem 'growl', :require => darwin_only('growl')
- gem 'rb-inotify', :require => linux_only('rb-inotify')
+ gem 'rb-fsevent', require: darwin_only('rb-fsevent')
+ gem 'growl', require: darwin_only('growl')
+ gem 'rb-inotify', require: linux_only('rb-inotify')
end
group :test do
- gem "simplecov", :require => false
+ gem "simplecov", require: false
gem "shoulda-matchers"
gem 'email_spec'
gem 'resque_spec'
diff --git a/Gemfile.lock b/Gemfile.lock
index 7dd69034..617c302b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -7,6 +7,7 @@ GIT
GIT
remote: https://github.com/gitlabhq/grack.git
revision: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
+ ref: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
specs:
grack (1.0.0)
rack (~> 1.4.1)
@@ -21,6 +22,14 @@ GIT
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
+GIT
+ remote: https://github.com/gitlabhq/grit_ext.git
+ revision: 212fd40bea61f3c6a167223768e7295dc32bbc10
+ ref: 212fd40bea61f3c6a167223768e7295dc32bbc10
+ specs:
+ grit_ext (0.6.0)
+ charlock_holmes (~> 0.6.9)
+
GIT
remote: https://github.com/gitlabhq/omniauth-ldap.git
revision: f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e
@@ -35,6 +44,7 @@ GIT
GIT
remote: https://github.com/gitlabhq/yaml_db.git
revision: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
+ ref: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
specs:
yaml_db (0.2.2)
@@ -90,7 +100,7 @@ GEM
carrierwave (0.6.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
- charlock_holmes (0.6.8)
+ charlock_holmes (0.6.9)
childprocess (0.3.2)
ffi (~> 1.0.6)
chosen-rails (0.9.8.3)
@@ -260,6 +270,8 @@ GEM
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
pyu-ruby-sasl (0.0.3.3)
+ quiet_assets (1.0.1)
+ railties (~> 3.1)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
@@ -411,7 +423,6 @@ DEPENDENCIES
capybara
capybara-webkit
carrierwave
- charlock_holmes
chosen-rails
coffee-rails (= 3.2.2)
colored
@@ -432,6 +443,7 @@ DEPENDENCIES
grack!
grape (~> 0.2.1)
grit!
+ grit_ext!
growl
guard-rspec
guard-spinach
@@ -454,6 +466,7 @@ DEPENDENCIES
pg
pry
pygments.rb (= 0.3.1)
+ quiet_assets (= 1.0.1)
rack-mini-profiler
rails (= 3.2.8)
rails-dev-tweaks
diff --git a/Procfile.production b/Procfile.production
deleted file mode 100644
index f1126486..00000000
--- a/Procfile.production
+++ /dev/null
@@ -1,2 +0,0 @@
-web: bundle exec rails s -p $PORT -e production
-worker: bundle exec rake environment resque:work RAILS_ENV=production QUEUE=*
diff --git a/ROADMAP.md b/ROADMAP.md
new file mode 100644
index 00000000..093a23f5
--- /dev/null
+++ b/ROADMAP.md
@@ -0,0 +1,19 @@
+## GitLab Roadmap
+
+### Common
+
+* Help page for service tasks like repos import, backup etc
+* Hide last push widget after following link
+* Add comment events
+* Dashboard/Project activity events filter
+
+### Issues
+
+* labels autocomplete via jquery autocomplete
+* Import/Export issues
+* Form: Assign to me link right to the selectbox
+
+### Merge Request
+
+* CI build status
+* Save code fragments with MR comments
diff --git a/VERSION b/VERSION
index 75a22a26..1c452795 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.3
+3.1.0pre
diff --git a/app/assets/images/event_filter_comments.png b/app/assets/images/event_filter_comments.png
new file mode 100644
index 00000000..aed113fa
Binary files /dev/null and b/app/assets/images/event_filter_comments.png differ
diff --git a/app/assets/images/event_filter_merged.png b/app/assets/images/event_filter_merged.png
new file mode 100644
index 00000000..30aea0b6
Binary files /dev/null and b/app/assets/images/event_filter_merged.png differ
diff --git a/app/assets/images/event_filter_push.png b/app/assets/images/event_filter_push.png
new file mode 100644
index 00000000..930faee6
Binary files /dev/null and b/app/assets/images/event_filter_push.png differ
diff --git a/app/assets/images/event_filter_team.png b/app/assets/images/event_filter_team.png
new file mode 100644
index 00000000..2dc66c85
Binary files /dev/null and b/app/assets/images/event_filter_team.png differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index d88f2a66..c4e9a1b0 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -17,6 +17,8 @@
//= require modernizr
//= require chosen-jquery
//= require raphael
+//= require g.raphael-min
+//= require g.bar-min
//= require branch-graph
//= require ace-src-noconflict/ace
//= require_tree .
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index 203a5b67..6c0c8886 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -1,57 +1,47 @@
+# Creates the variables for setting up GFM auto-completion
-###
- Creates the variables for setting up GFM auto-completion
-###
# Emoji
-window.autocompleteEmojiData = [];
-window.autocompleteEmojiTemplate = "
${name} ";
+data = []
+template = "${name} "
+window.autocompleteEmoji = {data, template}
# Team Members
-window.autocompleteMembersUrl = "";
-window.autocompleteMembersParams =
- private_token: ""
- page: 1
-window.autocompleteMembersData = [];
+url = '';
+params = {private_token: '', page: 1}
+window.autocompleteMembers = {data, url, params}
-
-
-###
- Add GFM auto-completion to all input fields, that accept GFM input.
-###
+# Add GFM auto-completion to all input fields, that accept GFM input.
window.setupGfmAutoComplete = ->
- ###
- Emoji
- ###
- $('.gfm-input').atWho ':',
- data: autocompleteEmojiData,
- tpl: autocompleteEmojiTemplate
+ $input = $('.js-gfm-input')
- ###
- Team Members
- ###
- $('.gfm-input').atWho '@', (query, callback) ->
+ # Emoji
+ $input.atWho ':',
+ data: autocompleteEmoji.data,
+ tpl: autocompleteEmoji.template
+
+ # Team Members
+ $input.atWho '@', (query, callback) ->
(getMoreMembers = ->
- $.getJSON(autocompleteMembersUrl, autocompleteMembersParams)
- .success (members) ->
- # pick the data we need
- newMembersData = $.map members, (m) -> m.name
+ $.getJSON(autocompleteMembers.url, autocompleteMembers.params).success (members) ->
+ # pick the data we need
+ newMembersData = $.map members, (m) -> m.name
- # add the new page of data to the rest
- $.merge autocompleteMembersData, newMembersData
+ # add the new page of data to the rest
+ $.merge autocompleteMembers.data, newMembersData
- # show the pop-up with a copy of the current data
- callback autocompleteMembersData[..]
+ # show the pop-up with a copy of the current data
+ callback autocompleteMembers.data[..]
- # are we past the last page?
- if newMembersData.length == 0
- # set static data and stop callbacks
- $('.gfm-input').atWho '@',
- data: autocompleteMembersData
- callback: null
- else
- # get next page
- getMoreMembers()
+ # are we past the last page?
+ if newMembersData.length is 0
+ # set static data and stop callbacks
+ $input.atWho '@',
+ data: autocompleteMembers.data
+ callback: null
+ else
+ # get next page
+ getMoreMembers()
# so the next request gets the next page
- autocompleteMembersParams.page += 1;
- ).call();
\ No newline at end of file
+ autocompleteMembers.params.page += 1
+ ).call()
diff --git a/app/assets/javascripts/graph.js.coffee b/app/assets/javascripts/graph.js.coffee
deleted file mode 100644
index 5fe8ae3f..00000000
--- a/app/assets/javascripts/graph.js.coffee
+++ /dev/null
@@ -1,10 +0,0 @@
-initGraphNav = ->
- $('.graph svg').css 'position', 'relative'
-
- $('body').bind 'keyup', (e) ->
- if e.keyCode is 37 # left
- $('.graph svg').animate left: '+=400'
- else if e.keyCode is 39 # right
- $('.graph svg').animate left: '-=400'
-
-window.initGraphNav = initGraphNav
diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index c3cf364f..db3ad7f7 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -1,6 +1,5 @@
-function switchToNewIssue(form){
+function switchToNewIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
- $(".issues_content").after(form);
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#new_issue_dialog").show("fade", { direction: "right" }, 150);
@@ -10,9 +9,8 @@ function switchToNewIssue(form){
});
}
-function switchToEditIssue(form){
+function switchToEditIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
- $(".issues_content").after(form);
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
@@ -33,8 +31,8 @@ function switchFromEditIssue(){
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").remove();
- $("#new_issue_dialog").remove();
+ $("#edit_issue_dialog").html("");
+ $("#new_issue_dialog").html("");
$('.add_new').show();
});
});
diff --git a/app/assets/javascripts/loader.js.coffee b/app/assets/javascripts/loader.js.coffee
deleted file mode 100644
index 66f8e8b1..00000000
--- a/app/assets/javascripts/loader.js.coffee
+++ /dev/null
@@ -1,5 +0,0 @@
-Loader =
- html: (width) ->
- $(' ').attr src: '/assets/ajax-loader.gif', width: width
-
-window.Loader = Loader
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
index 86b19162..04e6b2ef 100644
--- a/app/assets/javascripts/main.js.coffee
+++ b/app/assets/javascripts/main.js.coffee
@@ -7,29 +7,32 @@ window.slugify = (text) ->
window.ajaxGet = (url) ->
$.ajax({type: "GET", url: url, dataType: "script"})
- # Disable button if text field is empty
+# Disable button if text field is empty
window.disableButtonIfEmptyField = (field_selector, button_selector) ->
field = $(field_selector)
closest_submit = field.closest("form").find(button_selector)
closest_submit.disable() if field.val() is ""
- field.on "keyup", ->
- if $(this).val() is ""
+ field.on "input", ->
+ if $(@).val() is ""
closest_submit.disable()
else
closest_submit.enable()
$ ->
# Click a .one_click_select field, select the contents
- $(".one_click_select").live 'click', -> $(this).select()
+ $(".one_click_select").on 'click', -> $(@).select()
# Initialize chosen selects
$('select.chosen').chosen()
+ # Initialize tooltips
+ $('.has_tooltip').tooltip()
+
# Disable form buttons while a form is submitting
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
- buttons = $('[type="submit"]', this)
+ buttons = $('[type="submit"]', @)
switch e.type
when 'ajax:beforeSend', 'submit'
@@ -38,7 +41,7 @@ $ ->
buttons.enable()
# Show/Hide the profile menu when hovering the account box
- $('.account-box').hover -> $(this).toggleClass('hover')
+ $('.account-box').hover -> $(@).toggleClass('hover')
# Focus search field by pressing 's' key
$(document).keypress (e) ->
@@ -52,22 +55,22 @@ $ ->
# Commit show suppressed diff
$(".supp_diff_link").bind "click", ->
- $(this).next('table').show()
- $(this).remove()
+ $(@).next('table').show()
+ $(@).remove()
# Note markdown preview
$(document).on 'click', '#preview-link', (e) ->
- $('#preview-note').text('Loading...')
+ $('#preview-note').text 'Loading...'
- previewLinkText = if $(this).text() == 'Preview' then 'Edit' else 'Preview'
- $(this).text(previewLinkText)
+ previewLinkText = if $(@).text() is 'Preview' then 'Edit' else 'Preview'
+ $(@).text previewLinkText
note = $('#note_note').val()
- if note.trim().length == 0
- $('#preview-note').text("Nothing to preview.")
+ if note.trim().length is 0
+ $('#preview-note').text 'Nothing to preview.'
else
- $.post $(this).attr('href'), {note: note}, (data) ->
+ $.post $(@).attr('href'), {note: note}, (data) ->
$('#preview-note').html(data)
$('#preview-note, #note_note').toggle()
@@ -79,14 +82,14 @@ $ ->
$.fn.extend chosen: (options) ->
default_options = search_contains: "true"
$.extend default_options, options
- _chosen.apply this, [default_options]
+ _chosen.apply @, [default_options]
# Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: ->
- $(this).attr('disabled', 'disabled').addClass('disabled')
+ $(@).attr('disabled', 'disabled').addClass('disabled')
# Enable an element and remove the 'disabled' Bootstrap class
$.fn.extend enable: ->
- $(this).removeAttr('disabled').removeClass('disabled')
+ $(@).removeAttr('disabled').removeClass('disabled')
)(jQuery)
diff --git a/app/assets/javascripts/merge_requests.js b/app/assets/javascripts/merge_requests.js
index 0ab6f6e2..cc6b0771 100644
--- a/app/assets/javascripts/merge_requests.js
+++ b/app/assets/javascripts/merge_requests.js
@@ -115,4 +115,15 @@ var MergeRequest = {
$(".merge_in_progress").hide();
$(".automerge_widget.already_cannot_be_merged").show();
}
+};
+
+/*
+ * Filter merge requests
+ */
+function merge_requestsPage() {
+ $("#assignee_id").chosen();
+ $("#milestone_id").chosen();
+ $("#milestone_id, #assignee_id").on("change", function(){
+ $(this).closest("form").submit();
+ });
}
diff --git a/app/assets/javascripts/milestones.js.coffee b/app/assets/javascripts/milestones.js.coffee
index 13aba860..e40a69eb 100644
--- a/app/assets/javascripts/milestones.js.coffee
+++ b/app/assets/javascripts/milestones.js.coffee
@@ -5,3 +5,10 @@ $ ->
$('.milestone-issue-filter li').toggleClass('active')
$('.milestone-issue-filter tr[data-closed]').toggleClass('hide')
false
+
+ $('.milestone-merge-requests-filter tr[data-closed]').addClass('hide')
+
+ $('.milestone-merge-requests-filter ul.nav li a').click ->
+ $('.milestone-merge-requests-filter li').toggleClass('active')
+ $('.milestone-merge-requests-filter tr[data-closed]').toggleClass('hide')
+ false
diff --git a/app/assets/javascripts/projects.js.coffee b/app/assets/javascripts/projects.js.coffee
index 008fa8e9..3059723d 100644
--- a/app/assets/javascripts/projects.js.coffee
+++ b/app/assets/javascripts/projects.js.coffee
@@ -22,3 +22,10 @@ $ ->
# 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
diff --git a/app/assets/javascripts/snippets.js.coffee b/app/assets/javascripts/snippets.js.coffee
deleted file mode 100644
index af4385de..00000000
--- a/app/assets/javascripts/snippets.js.coffee
+++ /dev/null
@@ -1,6 +0,0 @@
-$ ->
- $('#snippets-table .snippet').live 'click', (e) ->
- if e.target.nodeName isnt 'A' and e.target.nodeName isnt 'INPUT'
- location.href = $(@).attr 'url'
- e.stopPropagation()
- false
diff --git a/app/assets/javascripts/tree.js.coffee b/app/assets/javascripts/tree.js.coffee
index 47d49abc..37adef70 100644
--- a/app/assets/javascripts/tree.js.coffee
+++ b/app/assets/javascripts/tree.js.coffee
@@ -17,23 +17,21 @@ $ ->
"ajax:beforeSend": -> $('.tree_progress').addClass("loading")
"ajax:complete": -> $('.tree_progress').removeClass("loading")
-# Maintain forward/back history while browsing the file tree
+ # Maintain forward/back history while browsing the file tree
+ ((window) ->
+ History = window.History
+ $ = window.jQuery
+ document = window.document
-((window) ->
- History = window.History
- $ = window.jQuery
- document = window.document
+ # Check to see if History.js is enabled for our Browser
+ unless History.enabled
+ return false
- # Check to see if History.js is enabled for our Browser
- unless History.enabled
- return false
+ $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
+ History.pushState(null, null, $(@).attr('href'))
+ return false
- $ ->
- $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
- History.pushState(null, null, $(@).attr('href'))
- return false
-
- History.Adapter.bind window, 'statechange', ->
- state = History.getState()
- window.ajaxGet(state.url)
-)(window)
+ History.Adapter.bind window, 'statechange', ->
+ state = History.getState()
+ window.ajaxGet(state.url)
+ )(window)
diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss
index 8ebbb53b..843b683f 100644
--- a/app/assets/stylesheets/common.scss
+++ b/app/assets/stylesheets/common.scss
@@ -670,3 +670,16 @@ pre {
padding:0;
}
}
+
+.milestone .progress {
+ margin-bottom: 0;
+ margin-top:4px;
+}
+
+.float-link {
+ float:left;
+ margin-right:15px;
+ .s16 {
+ margin-right:5px;
+ }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/common.scss b/app/assets/stylesheets/gitlab_bootstrap/common.scss
index 85bb5b22..25c355e9 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/common.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/common.scss
@@ -26,8 +26,10 @@
.underlined { border-bottom: 1px solid #CCC; }
.no-borders { border:none; }
.vlink { color: $link_color !important; }
+.underlined_link { text-decoration: underline; }
.borders { border: 1px solid #ccc; @include shade; }
.hint { font-style: italic; color: #999; }
+.light { color: #888 }
/** PILLS & TABS**/
.nav-pills a:hover { background-color:#888; }
@@ -66,10 +68,10 @@
.alert-message.error { @extend .alert-error; }
/** AVATARS **/
-img.avatar { float:left; margin-right:15px; width:40px; border:1px solid #ddd; padding:1px; }
-img.avatar.s16 { width:16px; height:16px; }
-img.avatar.s24 { width:24px; height:24px; }
-img.avatar.s32 { width:32px; height:32px; }
+img.avatar { float:left; margin-right:12px; width:40px; border:1px solid #ddd; padding:1px; }
+img.avatar.s16 { width:16px; height:16px; margin-right:6px; }
+img.avatar.s24 { width:24px; height:24px; margin-right:8px; }
+img.avatar.s32 { width:32px; height:32px; margin-right:10px; }
img.lil_av { padding-left: 4px; padding-right:3px; }
/** HELPERS **/
diff --git a/app/assets/stylesheets/gitlab_bootstrap/files.scss b/app/assets/stylesheets/gitlab_bootstrap/files.scss
index cbc58d22..580b7423 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/files.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -157,10 +157,15 @@
font-size:12px !important;
}
- table.highlighttable .linenodiv pre {
- text-align: right;
- padding-right: 4px;
- color:#666;
+ table.highlighttable .linenodiv {
+ a {
+ color: #666;
+ }
+ pre {
+ text-align: right;
+ padding-right: 4px;
+ color:#666;
+ }
}
}
}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/lists.scss b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
index a5d6bd0a..4fe45ecc 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/lists.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/lists.scss
@@ -21,7 +21,7 @@ ul {
.author { color: #999; }
p {
- padding-top:5px;
+ padding-top: 1px;
margin:0;
color:#222;
img {
@@ -31,3 +31,11 @@ ul {
}
}
}
+
+ol, ul {
+ &.styled {
+ li {
+ padding:2px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/gitlab_bootstrap/tables.scss b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
index 7a3bda2b..549cdfee 100644
--- a/app/assets/stylesheets/gitlab_bootstrap/tables.scss
+++ b/app/assets/stylesheets/gitlab_bootstrap/tables.scss
@@ -34,6 +34,11 @@ table {
border-color:#f1f1f1;
line-height:28px;
+ .s16 {
+ margin-top: 5px;
+ margin-right: 5px;
+ }
+
&:first-child {
border-left:1px solid #bbb;
}
diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss
index c821c3c1..259a57e5 100644
--- a/app/assets/stylesheets/main.scss
+++ b/app/assets/stylesheets/main.scss
@@ -3,10 +3,11 @@
@import 'font-awesome';
/** GitLab colors **/
-$link_color:#3A89A3;
-$blue_link: #2fa0bb;
-$style_color: #474d57;
+$link_color: #3A89A3;
+$blue_link: #2FA0BB;
+$style_color: #474D57;
$hover: #D9EDF7;
+$hover_border: #ADF;
/** GitLab Fonts **/
@font-face { font-family: Korolev; src: font-url('korolev-medium-compressed.otf'); }
@@ -19,9 +20,9 @@ $hover: #D9EDF7;
}
@mixin solid_shade {
- -moz-box-shadow: 0 0 0 3px #eee;
- -webkit-box-shadow: 0 0 0 3px #eee;
- box-shadow: 0 0 0 3px #eee;
+ -moz-box-shadow: 0 0 0 3px #f1f1f1;
+ -webkit-box-shadow: 0 0 0 3px #f1f1f1;
+ box-shadow: 0 0 0 3px #f1f1f1;
}
@mixin border-radius($radius) {
@@ -64,6 +65,14 @@ $hover: #D9EDF7;
background-image: -o-linear-gradient($from, $to);
}
+@mixin bg-light-gray-gradient {
+ background:#f1f1f1;
+ background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
+ background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
+ background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
+ background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
+}
+
@mixin bg-gray-gradient {
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
diff --git a/app/assets/stylesheets/ref_select.scss b/app/assets/stylesheets/ref_select.scss
index ed6760f1..377d0086 100644
--- a/app/assets/stylesheets/ref_select.scss
+++ b/app/assets/stylesheets/ref_select.scss
@@ -19,41 +19,14 @@
margin-right: 10px;
.chzn-drop {
- margin:7px 0;
min-width: 400px;
- border: 2px solid $blue_link;
- @include border-radius(4px);
-
.chzn-results {
max-height:300px;
-
- .group-result {
- color: $blue_link;
- }
- .active-result {
- &.highlighted {
- background: $blue_link;
- }
- }
}
-
.chzn-search input {
min-width:365px;
}
}
-
- .chzn-single {
- @include bg-gray-gradient;
-
- div {
- background:transparent;
- border-left:none;
- }
-
- span {
- font-weight: normal;
- }
- }
}
/** Fix for Search Dropdown Border **/
@@ -65,4 +38,55 @@
box-shadow: none;
}
}
+
+ .chzn-drop {
+ margin:7px 0;
+ min-width: 200px;
+ border: 1px solid #bbb;
+ border-radius:0;
+
+ .chzn-results {
+ margin-top: 5px;
+ max-height:300px;
+
+ .group-result {
+ color: $style_color;
+ border-bottom: 1px solid #EEE;
+ padding: 8px;
+ }
+ .active-result {
+ border-radius: 0;
+
+ &.highlighted {
+ background: $hover;
+ color: $style_color;
+ }
+ &.result-selected {
+ background: #EEE;
+ border-left: 4px solid #CCC;
+ }
+ }
+ }
+
+ .chzn-search {
+ @include bg-gray-gradient;
+ input {
+ min-width:165px;
+ border-color: #CCC;
+ }
+ }
+ }
+
+ .chzn-single {
+ @include bg-light-gray-gradient;
+
+ div {
+ background:transparent;
+ border-left:none;
+ }
+
+ span {
+ font-weight: normal;
+ }
+ }
}
diff --git a/app/assets/stylesheets/sections/commits.scss b/app/assets/stylesheets/sections/commits.scss
index 139d7347..4f9360ad 100644
--- a/app/assets/stylesheets/sections/commits.scss
+++ b/app/assets/stylesheets/sections/commits.scss
@@ -47,12 +47,15 @@
padding-left: 32px;
}
- .author,
- .committer {
+ .author a,
+ .committer a {
font-size:14px;
line-height:22px;
text-shadow:0 1px 1px #fff;
color:#777;
+ &:hover {
+ color: #999;
+ }
}
.avatar {
@@ -227,6 +230,9 @@
.commit-author-name {
color: #777;
+ &:hover {
+ color: #999;
+ }
}
}
diff --git a/app/assets/stylesheets/sections/events.scss b/app/assets/stylesheets/sections/events.scss
index 17df600c..369ebc81 100644
--- a/app/assets/stylesheets/sections/events.scss
+++ b/app/assets/stylesheets/sections/events.scss
@@ -43,6 +43,7 @@
.event-body {
p {
color:#555;
+ padding-top: 5px;
}
.event-info {
color:#666;
@@ -115,3 +116,29 @@
margin: -3px;
}
}
+
+/**
+ * Event filter
+ *
+ */
+.event_filter {
+ position: absolute;
+ width: 40px;
+ margin-left: -50px;
+
+ .filter_icon {
+ float: left;
+ border-left: 3px solid #4bc;
+ padding: 7px;
+ background: #f9f9f9;
+ margin-bottom: 10px;
+ img {
+ width:20px;
+ }
+
+ &.inactive {
+ border-left: 3px solid #EEE;
+ opacity: 0.5;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index 3ad9d6f7..93622d61 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -44,7 +44,7 @@
img.avatar {
width:32px;
- margin-top:4px;
+ margin-top:1px;
}
}
}
diff --git a/app/assets/stylesheets/sections/merge_requests.scss b/app/assets/stylesheets/sections/merge_requests.scss
index c932f0fc..78e3fa39 100644
--- a/app/assets/stylesheets/sections/merge_requests.scss
+++ b/app/assets/stylesheets/sections/merge_requests.scss
@@ -71,7 +71,7 @@ li.merge_request {
padding:7px 10px;
img.avatar {
width: 32px;
- margin-top: 4px;
+ margin-top: 1px;
}
p {
padding: 0px;
@@ -121,3 +121,20 @@ li.merge_request {
.mr_direction_tip {
margin-top:40px
}
+
+.merge_requests_form_box {
+ @extend .main_box;
+ .merge_requests_middle_box {
+ @extend .middle_box_content;
+ height:30px;
+ .merge_requests_assignee {
+ @extend .span6;
+ float:left;
+ }
+ .merge_requests_milestone {
+ @extend .span4;
+ float:left;
+ }
+ }
+}
+
diff --git a/app/assets/stylesheets/sections/tree.scss b/app/assets/stylesheets/sections/tree.scss
index e17487fd..f6bdb0f3 100644
--- a/app/assets/stylesheets/sections/tree.scss
+++ b/app/assets/stylesheets/sections/tree.scss
@@ -57,10 +57,7 @@
padding-right: 8px;
img.avatar {
- border: 0 none;
- float: none;
- margin-right: 0;
- padding: 0;
+ margin-top: 0;
width: 16px;
}
}
@@ -75,6 +72,15 @@
}
}
}
+
+ .blame {
+ img.avatar {
+ border: 0 none;
+ float: none;
+ margin: 0;
+ padding: 0;
+ }
+ }
}
.tree-btn-group {
diff --git a/app/assets/stylesheets/themes/ui_mars.scss b/app/assets/stylesheets/themes/ui_mars.scss
index c630f388..77507569 100644
--- a/app/assets/stylesheets/themes/ui_mars.scss
+++ b/app/assets/stylesheets/themes/ui_mars.scss
@@ -37,9 +37,6 @@
background-image: -o-linear-gradient(#595D63 6.6%, #202227);
background-position:0 0;
color:#fff;
- i {
- @extend .icon-white;
- }
}
border: 1px solid #31363E;
diff --git a/app/assets/stylesheets/themes/ui_modern.scss b/app/assets/stylesheets/themes/ui_modern.scss
index 1f0d7955..8b942149 100644
--- a/app/assets/stylesheets/themes/ui_modern.scss
+++ b/app/assets/stylesheets/themes/ui_modern.scss
@@ -70,9 +70,6 @@
color:#ccc;
&:hover {
color:#fff;
- i {
- @extend .icon-white;
- }
}
border: none;
box-shadow:none;
diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb
index b3548ed8..e43e5a07 100644
--- a/app/contexts/commit_load_context.rb
+++ b/app/contexts/commit_load_context.rb
@@ -21,7 +21,7 @@ class CommitLoadContext < BaseContext
result[:notes_count] = line_notes.count + project.commit_notes(commit).count
begin
- result[:suppress_diff] = true if commit.diffs.size > 200 && !params[:force_show_diff]
+ result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff]
rescue Grit::Git::GitTimeout
result[:suppress_diff] = true
result[:status] = :huge_commit
diff --git a/app/contexts/merge_requests_load_context.rb b/app/contexts/merge_requests_load_context.rb
index e7dbdd28..4ec66cd9 100644
--- a/app/contexts/merge_requests_load_context.rb
+++ b/app/contexts/merge_requests_load_context.rb
@@ -1,3 +1,5 @@
+# Build collection of Merge Requests
+# based on filtering passed via params for @project
class MergeRequestsLoadContext < BaseContext
def execute
type = params[:f]
@@ -9,8 +11,21 @@ class MergeRequestsLoadContext < BaseContext
when 'closed' then merge_requests.closed
when 'assigned-to-me' then merge_requests.opened.assigned(current_user)
else merge_requests.opened
- end.page(params[:page]).per(20)
+ end
- merge_requests.includes(:author, :project).order("closed, created_at desc")
+ merge_requests = merge_requests.page(params[:page]).per(20)
+ merge_requests = merge_requests.includes(:author, :project).order("closed, created_at desc")
+
+ # Filter by specific assignee_id (or lack thereof)?
+ if params[:assignee_id].present?
+ merge_requests = merge_requests.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
+ end
+
+ # Filter by specific milestone_id (or lack thereof)?
+ if params[:milestone_id].present?
+ merge_requests = merge_requests.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
+ end
+
+ merge_requests
end
end
diff --git a/app/contexts/search_context.rb b/app/contexts/search_context.rb
index 6e5e8c5e..9becb8d6 100644
--- a/app/contexts/search_context.rb
+++ b/app/contexts/search_context.rb
@@ -13,6 +13,7 @@ class SearchContext
result[:projects] = Project.where(id: project_ids).search(query).limit(10)
result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10)
result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10)
+ result[:wiki_pages] = Wiki.where(project_id: project_ids).search(query).limit(10)
result
end
@@ -20,7 +21,8 @@ class SearchContext
@result ||= {
projects: [],
merge_requests: [],
- issues: []
+ issues: [],
+ wiki_pages: []
}
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b597795a..ef6fc81a 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -9,19 +9,28 @@ class ApplicationController < ActionController::Base
helper_method :abilities, :can?
rescue_from Gitlab::Gitolite::AccessDenied do |exception|
+ log_exception(exception)
render "errors/gitolite", layout: "errors", status: 500
end
rescue_from Encoding::CompatibilityError do |exception|
+ log_exception(exception)
render "errors/encoding", layout: "errors", status: 500
end
rescue_from ActiveRecord::RecordNotFound do |exception|
+ log_exception(exception)
render "errors/not_found", layout: "errors", status: 404
end
protected
+ def log_exception(exception)
+ application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace
+ application_trace.map!{ |t| " #{t}\n" }
+ logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}"
+ end
+
def reject_blocked!
if current_user && current_user.blocked
sign_out current_user
diff --git a/app/controllers/blob_controller.rb b/app/controllers/blob_controller.rb
index 30069d19..d4a45d95 100644
--- a/app/controllers/blob_controller.rb
+++ b/app/controllers/blob_controller.rb
@@ -1,7 +1,6 @@
# Controller for viewing a file's blame
class BlobController < ProjectResourceController
include ExtractsPath
- include Gitlab::Encode
# Authorize
before_filter :authorize_read_project!
@@ -12,16 +11,9 @@ class BlobController < ProjectResourceController
def show
if @tree.is_blob?
- if @tree.text?
- encoding = detect_encoding(@tree.data)
- mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain"
- else
- mime_type = @tree.mime_type
- end
-
send_data(
@tree.data,
- type: mime_type,
+ type: @tree.mime_type,
disposition: 'inline',
filename: @tree.name
)
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index af23f970..012d8676 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,12 +1,17 @@
class DashboardController < ApplicationController
respond_to :html
+ before_filter :event_filter, only: :index
+
def index
@groups = Group.where(id: current_user.projects.pluck(:group_id))
@projects = current_user.projects_with_events
@projects = @projects.page(params[:page]).per(30)
- @events = Event.in_projects(current_user.project_ids).limit(20).offset(params[:offset] || 0)
+ @events = Event.in_projects(current_user.project_ids)
+ @events = @event_filter.apply_filter(@events)
+ @events = @events.limit(20).offset(params[:offset] || 0)
+
@last_push = current_user.recent_push
respond_to do |format|
@@ -34,4 +39,8 @@ class DashboardController < ApplicationController
format.atom { render layout: false }
end
end
+
+ def event_filter
+ @event_filter ||= EventFilter.new(params[:event_filter])
+ end
end
diff --git a/app/controllers/milestones_controller.rb b/app/controllers/milestones_controller.rb
index fa202cf4..fadfee2d 100644
--- a/app/controllers/milestones_controller.rb
+++ b/app/controllers/milestones_controller.rb
@@ -31,7 +31,8 @@ class MilestonesController < ProjectResourceController
def show
@issues = @milestone.issues
- @users = @milestone.participants
+ @users = UserDecorator.decorate(@milestone.participants)
+ @merge_requests = @milestone.merge_requests
respond_to do |format|
format.html
diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb
index 2b8e18f6..38cfa896 100644
--- a/app/controllers/profile_controller.rb
+++ b/app/controllers/profile_controller.rb
@@ -22,7 +22,7 @@ class ProfileController < ApplicationController
flash[:notice] = "Password was successfully updated. Please login with it"
redirect_to new_user_session_path
else
- render action: "password"
+ render 'account'
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 13b264a4..7d70852f 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,4 +1,4 @@
-require Rails.root.join('lib', 'gitlab', 'graph_commit')
+require Rails.root.join('lib', 'gitlab', 'graph', 'json_builder')
class ProjectsController < ProjectResourceController
skip_before_filter :project, only: [:new, :create]
@@ -79,7 +79,9 @@ class ProjectsController < ProjectResourceController
end
def graph
- @days_json, @commits_json = Gitlab::GraphCommit.to_graph(project)
+ graph = Gitlab::Graph::JsonBuilder.new(project)
+
+ @days_json, @commits_json = graph.days_json, graph.commits_json
end
def destroy
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 977ccea7..b48d5ec7 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -1,5 +1,4 @@
class RefsController < ProjectResourceController
- include Gitlab::Encode
# Authorize
before_filter :authorize_read_project!
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index 18b240e4..7678fbff 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -16,9 +16,14 @@ class RepositoriesController < ProjectResourceController
@tags = @project.tags
end
+ def stats
+ @stats = Gitlab::GitStats.new(@project.repo, @project.root_ref)
+ @graph = @stats.graph
+ end
+
def archive
unless can?(current_user, :download_code, @project)
- render_404 and return
+ render_404 and return
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 1dc8507e..4f45f9dd 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,5 +5,6 @@ class SearchController < ApplicationController
@projects = result[:projects]
@merge_requests = result[:merge_requests]
@issues = result[:issues]
+ @wiki_pages = result[:wiki_pages]
end
end
diff --git a/app/controllers/tree_controller.rb b/app/controllers/tree_controller.rb
index e507fb51..725f48fa 100644
--- a/app/controllers/tree_controller.rb
+++ b/app/controllers/tree_controller.rb
@@ -26,15 +26,14 @@ class TreeController < ProjectResourceController
end
def update
- file_editor = Gitlab::FileEditor.new(current_user, @project, @ref)
- update_status = file_editor.update(
- @path,
+ edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path)
+ updated_successfully = edit_file_action.commit!(
params[:content],
params[:commit_message],
params[:last_commit]
)
- if update_status
+ if updated_successfully
redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited"
else
flash[:notice] = "Your changes could not be commited, because the file has been changed"
diff --git a/app/decorators/commit_decorator.rb b/app/decorators/commit_decorator.rb
index 24723941..69d5b178 100644
--- a/app/decorators/commit_decorator.rb
+++ b/app/decorators/commit_decorator.rb
@@ -47,21 +47,15 @@ class CommitDecorator < ApplicationDecorator
# Otherwise it will link to the author email as specified in the commit.
#
# options:
- # avatar: true will prepend avatar image
- def author_link(options)
- text = if options[:avatar]
- avatar = h.image_tag h.gravatar_icon(author_email), class: "avatar", width: 16
- "#{avatar} #{author_name}"
- else
- author_name
- end
- team_member = @project.try(:team_member_by_name_or_email, author_name, author_email)
+ # avatar: true will prepend the avatar image
+ # size: size of the avatar image in px
+ def author_link(options = {})
+ person_link(options.merge source: :author)
+ end
- if team_member.nil?
- h.mail_to author_email, text.html_safe, class: "commit-author-link"
- else
- h.link_to text, h.project_team_member_path(@project, team_member), class: "commit-author-link"
- end
+ # Just like #author_link but for the committer.
+ def committer_link(options = {})
+ person_link(options.merge source: :committer)
end
protected
@@ -69,4 +63,30 @@ class CommitDecorator < ApplicationDecorator
def no_commit_message
"--no commit message"
end
+
+ # Private: Returns a link to a person. If the person has a matching user and
+ # is a member of the current @project it will link to the team member page.
+ # Otherwise it will link to the person email as specified in the commit.
+ #
+ # options:
+ # source: one of :author or :committer
+ # avatar: true will prepend the avatar image
+ # size: size of the avatar image in px
+ def person_link(options = {})
+ 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]
+ %Q{#{avatar} #{source_name} }
+ else
+ source_name
+ end
+ team_member = @project.try(:team_member_by_name_or_email, source_name, source_email)
+
+ if team_member.nil?
+ h.mail_to source_email, text.html_safe, class: "commit-#{options[:source]}-link"
+ else
+ h.link_to text, h.project_team_member_path(@project, team_member), class: "commit-#{options[:source]}-link"
+ end
+ end
end
diff --git a/app/decorators/tree_decorator.rb b/app/decorators/tree_decorator.rb
index eb3859a9..c12227af 100644
--- a/app/decorators/tree_decorator.rb
+++ b/app/decorators/tree_decorator.rb
@@ -8,14 +8,14 @@ class TreeDecorator < ApplicationDecorator
#parts = parts[0...-1] if is_blob?
- yield(h.link_to("..", "#", remote: true)) if parts.count > max_links
+ yield(h.link_to("..", "#")) if parts.count > max_links
parts.each do |part|
part_path = File.join(part_path, part) unless part_path.empty?
part_path = part if part_path.empty?
next unless parts.last(2).include?(part) if parts.count > max_links
- yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path)), remote: true))
+ yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path))))
end
end
end
diff --git a/app/decorators/user_decorator.rb b/app/decorators/user_decorator.rb
new file mode 100644
index 00000000..af9c6a63
--- /dev/null
+++ b/app/decorators/user_decorator.rb
@@ -0,0 +1,11 @@
+class UserDecorator < ApplicationDecorator
+ decorates :user
+
+ def avatar_image size = 16
+ h.image_tag h.gravatar_icon(self.email, size), class: "avatar #{"s#{size}"}", width: size
+ end
+
+ def tm_of(project)
+ project.team_member_by_id(self.id)
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a4d36c9b..cba34c96 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -36,7 +36,7 @@ module ApplicationHelper
else
gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
user_email.strip!
- "#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=identicon"
+ "#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=mm"
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 4b35b0ac..135d002f 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -65,4 +65,9 @@ module CommitsHelper
end
end
+ def commit_to_html commit
+ if commit.model
+ escape_javascript(render 'commits/commit', commit: commit)
+ end
+ end
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 0eb87caa..a2548a23 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -33,4 +33,22 @@ module EventsHelper
image_tag event_image_path
end
end
+
+ def event_filter_link key, tooltip
+ key = key.to_s
+
+ filter = @event_filter.options key
+
+ inactive = if @event_filter.active? key
+ nil
+ else
+ 'inactive'
+ end
+
+ content_tag :div, class: "filter_icon #{inactive}" do
+ link_to dashboard_path(event_filter: filter), class: 'has_tooltip', 'data-original-title' => tooltip do
+ image_tag "event_filter_#{key}.png"
+ end
+ end
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 468ace15..7c302ef4 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -10,5 +10,9 @@ module ProjectsHelper
def link_to_project project
link_to project.name, project
end
+
+ def tm_path team_member
+ project_team_member_path(@project, team_member)
+ end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 4fe87a25..0f2b695e 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -67,4 +67,29 @@ module TreeHelper
can?(current_user, :push_code, @project)
end
end
+
+ # Breadcrumb links for a Project and, if applicable, a tree path
+ def breadcrumbs
+ return unless @project && @ref
+
+ # Add the root project link and the arrow icon
+ crumbs = content_tag(:li) do
+ content_tag(:span, nil, class: 'arrow') +
+ link_to(@project.name, project_commits_path(@project, @ref))
+ end
+
+ if @path
+ parts = @path.split('/')
+
+ parts.each_with_index do |part, i|
+ crumbs += content_tag(:span, '/', class: 'divider')
+ crumbs += content_tag(:li) do
+ # The text is just the individual part, but the link needs all the parts before it
+ link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
+ end
+ end
+ end
+
+ crumbs.html_safe
+ end
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index a070e830..5efb20ce 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -1,9 +1,13 @@
class Commit
include ActiveModel::Conversion
- include Gitlab::Encode
include StaticModel
extend ActiveModel::Naming
+ # Safe amount of files with diffs in one commit to render
+ # Used to prevent 500 error on huge commits by suppressing diff
+ #
+ DIFF_SAFE_SIZE = 100
+
attr_accessor :commit, :head, :refs
delegate :message, :authored_date, :committed_date, :parents, :sha,
@@ -107,7 +111,7 @@ class Commit
end
def safe_message
- @safe_message ||= utf8 message
+ @safe_message ||= message
end
def created_at
@@ -119,7 +123,7 @@ class Commit
end
def author_name
- utf8 author.name
+ author.name
end
# Was this commit committed by a different person than the original author?
@@ -128,7 +132,7 @@ class Commit
end
def committer_name
- utf8 committer.name
+ committer.name
end
def committer_email
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 3dd1c8c8..1acdfdd3 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -7,8 +7,6 @@ class Issue < ActiveRecord::Base
acts_as_taggable_on :labels
- belongs_to :milestone
-
validates :description, length: { within: 0..2000 }
def self.open_for(user)
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 70780b75..16e13db7 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1,10 +1,11 @@
require Rails.root.join("app/models/commit")
+require Rails.root.join("app/roles/static_model")
class MergeRequest < ActiveRecord::Base
include IssueCommonality
include Votes
- attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch,
+ attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id,
:author_id_of_changes
attr_accessor :should_remove_source_branch
@@ -26,6 +27,10 @@ class MergeRequest < ActiveRecord::Base
where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
end
+ def self.find_all_by_milestone(milestone)
+ where("milestone_id = :milestone_id", milestone_id: milestone)
+ end
+
def human_state
states = {
CAN_BE_MERGED => "can_be_merged",
@@ -60,7 +65,7 @@ class MergeRequest < ActiveRecord::Base
end
def check_if_can_be_merged
- self.state = if Gitlab::Merge.new(self, self.author).can_be_merged?
+ self.state = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
CAN_BE_MERGED
else
CANNOT_BE_MERGED
@@ -167,7 +172,7 @@ class MergeRequest < ActiveRecord::Base
end
def automerge!(current_user)
- if Gitlab::Merge.new(self, current_user).merge! && self.unmerged_commits.empty?
+ if Gitlab::Satellite::MergeAction.new(current_user, self).merge! && self.unmerged_commits.empty?
self.merge!(current_user.id)
true
end
@@ -212,5 +217,6 @@ end
# st_diffs :text(4294967295
# merged :boolean default(FALSE), not null
# state :integer default(1), not null
+# milestone_id :integer
#
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 06c09431..41412a13 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -3,6 +3,7 @@ class Milestone < ActiveRecord::Base
belongs_to :project
has_many :issues
+ has_many :merge_requests
validates :title, presence: true
validates :project, presence: true
@@ -15,8 +16,20 @@ class Milestone < ActiveRecord::Base
User.where(id: issues.pluck(:assignee_id))
end
+ def open_items_count
+ self.issues.opened.count + self.merge_requests.opened.count
+ end
+
+ def closed_items_count
+ self.issues.closed.count + self.merge_requests.closed.count
+ end
+
+ def total_items_count
+ self.issues.count + self.merge_requests.count
+ end
+
def percent_complete
- ((self.issues.closed.count * 100) / self.issues.count).abs
+ ((closed_items_count * 100) / total_items_count).abs
rescue ZeroDivisionError
100
end
diff --git a/app/models/note.rb b/app/models/note.rb
index e2f4a89d..d7701c38 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -23,13 +23,13 @@ class Note < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader
# Scopes
- scope :common, where(noteable_id: nil)
- scope :today, where("created_at >= :date", date: Date.today)
- scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
+ scope :common, ->{ where(noteable_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)) }
- scope :fresh, order("created_at ASC, id ASC")
- scope :inc_author_project, includes(:project, :author)
- scope :inc_author, includes(:author)
+ scope :fresh, ->{ order("created_at ASC, id ASC") }
+ scope :inc_author_project, ->{ includes(:project, :author) }
+ scope :inc_author, ->{ includes(:author) }
def self.create_status_change_note(noteable, author, status)
create({
diff --git a/app/models/project.rb b/app/models/project.rb
index 53fe0ee1..5b59f227 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -104,8 +104,10 @@ class Project < ActiveRecord::Base
end
def repo_name
- if path == "gitolite-admin"
- errors.add(:path, " like 'gitolite-admin' is not allowed")
+ denied_paths = %w(gitolite-admin groups projects dashboard)
+
+ if denied_paths.include?(path)
+ errors.add(:path, "like #{path} is not allowed")
end
end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index e4297a71..c3dfd4c7 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -8,7 +8,7 @@ class Tree
def initialize(raw_tree, project, ref = nil, path = nil)
@project, @ref, @path = project, ref, path
@tree = if path.present?
- raw_tree / path.dup.force_encoding('ascii-8bit')
+ raw_tree / path
else
raw_tree
end
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index b1f41d63..895c2896 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -15,6 +15,12 @@ class Wiki < ActiveRecord::Base
slug
end
+ class << self
+ def search(query)
+ where("title like :query OR content like :query", query: "%#{query}%")
+ end
+ end
+
protected
def self.regenerate_from wiki
diff --git a/app/roles/issue_commonality.rb b/app/roles/issue_commonality.rb
index 2d10bfec..79831cdc 100644
--- a/app/roles/issue_commonality.rb
+++ b/app/roles/issue_commonality.rb
@@ -6,6 +6,7 @@ module IssueCommonality
belongs_to :project
belongs_to :author, class_name: "User"
belongs_to :assignee, class_name: "User"
+ belongs_to :milestone
has_many :notes, as: :noteable, dependent: :destroy
validates :project, presence: true
diff --git a/app/roles/repository.rb b/app/roles/repository.rb
index 8942eaea..88468117 100644
--- a/app/roles/repository.rb
+++ b/app/roles/repository.rb
@@ -41,7 +41,7 @@ module Repository
end
def satellite
- @satellite ||= Gitlab::Satellite.new(self)
+ @satellite ||= Gitlab::Satellite::Satellite.new(self)
end
def has_post_receive_file?
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index c742fb33..78df8f2d 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -43,7 +43,7 @@
%b
Owner:
%td
- = @admin_project.owner.name
+ = @admin_project.owner_name || '(deleted)'
%tr
%td
%b
diff --git a/app/views/admin/resque/show.html.haml b/app/views/admin/resque/show.html.haml
index 8850e378..41254a6b 100644
--- a/app/views/admin/resque/show.html.haml
+++ b/app/views/admin/resque/show.html.haml
@@ -1,4 +1,4 @@
%h3.page_title Resque
%br
.ui-box
- %iframe{src: resque_url, width: '100%', height: 600, style: "border: none"}
+ %iframe{src: resque_path, width: '100%', height: 600, style: "border: none"}
diff --git a/app/views/blame/_head.html.haml b/app/views/blame/_head.html.haml
index 175719b1..85da1805 100644
--- a/app/views/blame/_head.html.haml
+++ b/app/views/blame/_head.html.haml
@@ -4,7 +4,4 @@
= nav_link(controller: :refs) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.right
- .input-prepend.project_clone_holder
- %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
- %button{class: "btn small", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.web_protocol.upcase
- = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
+ = render "shared/clone_panel"
diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml
index 5c3231e2..c5192c53 100644
--- a/app/views/blame/show.html.haml
+++ b/app/views/blame/show.html.haml
@@ -15,7 +15,7 @@
.file_title
%i.icon-file
%span.file_name
- = @tree.name.force_encoding('utf-8')
+ = @tree.name
%small= number_to_human_size @tree.size
%span.options= render "tree/blob_actions"
.file_content.blame
@@ -24,9 +24,7 @@
- commit = Commit.new(commit)
- commit = CommitDecorator.decorate(commit)
%tr
- %td.author
- = image_tag gravatar_icon(commit.author_email, 16)
- = commit.author_name
+ %td.author= commit.author_link avatar: true, size: 16
%td.blame_commit
%code= link_to commit.short_id, project_commit_path(@project, commit)
@@ -34,4 +32,4 @@
%td.lines
= preserve do
%pre
- = Gitlab::Encode.utf8 lines.join("\n")
+ = lines.join("\n")
diff --git a/app/views/commits/huge_commit.html.haml b/app/views/commit/huge_commit.html.haml
similarity index 100%
rename from app/views/commits/huge_commit.html.haml
rename to app/views/commit/huge_commit.html.haml
diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml
index 9abadc5d..156ff1e9 100644
--- a/app/views/commits/_commit.html.haml
+++ b/app/views/commits/_commit.html.haml
@@ -4,9 +4,8 @@
%strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right"
%p
= link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
- %strong.commit-author-name= commit.author_name
- %span.dash –
- = image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
+ = commit.author_link avatar: true, size: 24
+
= link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title"
%span.committed_ago
diff --git a/app/views/commits/_commit_box.html.haml b/app/views/commits/_commit_box.html.haml
index ece0df22..26753a14 100644
--- a/app/views/commits/_commit_box.html.haml
+++ b/app/views/commits/_commit_box.html.haml
@@ -18,16 +18,15 @@
.commit-info
.row
.span5
- = image_tag gravatar_icon(@commit.author_email, 40), class: "avatar"
.author
- %strong= @commit.author_name
+ %strong= @commit.author_link avatar: true, size: 40
authored
%time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.authored_date)} ago
- if @commit.different_committer?
.committer
→
- %strong= @commit.committer_name
+ %strong= @commit.committer_link
committed
%time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.committed_date)} ago
diff --git a/app/views/commits/_diffs.html.haml b/app/views/commits/_diffs.html.haml
index 026fe27e..70fff53c 100644
--- a/app/views/commits/_diffs.html.haml
+++ b/app/views/commits/_diffs.html.haml
@@ -1,11 +1,11 @@
- if @suppress_diff
.alert-message.block-message
%p
- %strong Warning! Large commit with more then 200 files changed.
+ %strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
%p To prevent performance issue we rejected diff information.
%p
But if you still want to see diff
- = link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "dark"
+ = link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "underlined_link"
%p.cgray
Showing #{pluralize(diffs.count, "changed file")}
@@ -35,10 +35,10 @@
- if file.text?
= render "commits/text_file", diff: diff, index: i
- elsif file.image?
- - if diff.renamed_file || diff.new_file || diff.deleted_file
+ - if diff.renamed_file || diff.new_file || diff.deleted_file
.diff_file_content_image
%img{class: image_diff_class(diff), src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
- - else
+ - else
- old_file = (@commit.prev_commit.tree / diff.old_path)
.diff_file_content_image.img_compared
%img{class: "diff_image_removed", src: "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"}
diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml
index c001c2f7..2ec1d24b 100644
--- a/app/views/commits/_head.html.haml
+++ b/app/views/commits/_head.html.haml
@@ -16,6 +16,11 @@
Tags
%span.badge= @project.tags.length
+ = nav_link(controller: :repositories, action: :stats) do
+ = link_to stats_project_repository_path(@project) do
+ Stats
+
+
- if current_controller?(:commits) && current_user.private_token
%li.right
%span.rss-icon
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index ac063638..9451a038 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -2,14 +2,7 @@
- if @path.present?
%ul.breadcrumb
- %li
- %span.arrow
- = link_to project_commits_path(@project) do
- = @project.name
- %span.divider
- \/
- %li
- %a{href: "#"}= @path.split("/").join(" / ")
+ = breadcrumbs
%div{id: dom_id(@project)}
#commits_list= render "commits"
diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml
index 6c4ff96b..d0882c6d 100644
--- a/app/views/dashboard/index.html.haml
+++ b/app/views/dashboard/index.html.haml
@@ -3,10 +3,17 @@
.activities.span8
= render "events/event_last_push", event: @last_push
= render 'shared/no_ssh'
+
+ .event_filter
+ = event_filter_link EventFilter.push, 'Push events'
+ = event_filter_link EventFilter.merged, 'Merge events'
+ = event_filter_link EventFilter.comments, 'Comments'
+ = event_filter_link EventFilter.team, 'Team'
+
- if @events.any?
.content_list= render @events
- else
- %h4.nothing_here_message Projects activity will be displayed here
+ %p.nothing_here_message Projects activity will be displayed here
.loading.hide
.side
- if @groups.present?
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 07ecf70b..38192d71 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -14,8 +14,9 @@
= f.submit "Sign in", :class => "primary btn wide"
.right
= render :partial => "devise/shared/links"
- - if devise_mapping.omniauthable?
- %hr/
- - resource_class.omniauth_providers.each do |provider|
- %span
- = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
+ .clearfix
+ - if devise_mapping.omniauthable? && resource_class.omniauth_providers.present?
+ %div
+ - resource_class.omniauth_providers.each do |provider|
+ %span
+ = link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
diff --git a/app/views/help/system_hooks.html.haml b/app/views/help/system_hooks.html.haml
index 736c818b..c25b60de 100644
--- a/app/views/help/system_hooks.html.haml
+++ b/app/views/help/system_hooks.html.haml
@@ -5,9 +5,10 @@
%hr
%p.slead
- Your GitLab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
+ Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
%br
- System Hooks can be used for logging or change information in LDAP server.
+ %br
+ System Hooks can be used, e.g. for logging or changing information in a LDAP server.
%br
%h5 Hooks request example:
= render "admin/hooks/data_ex"
diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml
index 2ba72975..670b4e05 100644
--- a/app/views/issues/_form.html.haml
+++ b/app/views/issues/_form.html.haml
@@ -12,7 +12,7 @@
= f.label :title do
%strong= "Subject *"
.input
- = f.text_field :title, maxlength: 255, class: "xxlarge gfm-input", autofocus: true
+ = f.text_field :title, maxlength: 255, class: "xxlarge js-gfm-input", autofocus: true
.issue_middle_block
.issue_assignee
= f.label :assignee_id do
@@ -37,7 +37,7 @@
.clearfix
= f.label :description, "Details"
.input
- = f.text_area :description, maxlength: 2000, class: "xxlarge gfm-input", rows: 14
+ = f.text_area :description, maxlength: 2000, class: "xxlarge js-gfm-input", rows: 14
%p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
diff --git a/app/views/issues/edit.js.haml b/app/views/issues/edit.js.haml
index 76d9e02e..a994572f 100644
--- a/app/views/issues/edit.js.haml
+++ b/app/views/issues/edit.js.haml
@@ -1,5 +1,4 @@
:plain
- var edit_issue_dialog = $("
");
- edit_issue_dialog.html("#{escape_javascript(render('form'))}");
- switchToEditIssue(edit_issue_dialog);
+ $("#edit_issue_dialog").html("#{escape_javascript(render('form'))}");
+ switchToEditIssue();
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index 22c34baa..d89b183d 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -58,6 +58,8 @@
%ul#issues-table.unstyled.issues_table
= render "issues"
+#new_issue_dialog
+#edit_issue_dialog
:javascript
$(function(){
diff --git a/app/views/issues/new.js.haml b/app/views/issues/new.js.haml
index afa2b86e..4cbcc563 100644
--- a/app/views/issues/new.js.haml
+++ b/app/views/issues/new.js.haml
@@ -1,4 +1,3 @@
:plain
- var new_issue_dialog = $("
");
- new_issue_dialog.html("#{escape_javascript(render('form'))}");
- switchToNewIssue(new_issue_dialog);
+ $("#new_issue_dialog").html("#{escape_javascript(render('form'))}");
+ switchToNewIssue();
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 7f89bdf0..4eed58e2 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -8,9 +8,7 @@
GITLAB
%span.separator
%h1.project_name= title
- .search
- = form_tag search_path, method: :get do |f|
- = text_field_tag "search", nil, placeholder: "Search", class: "search-input"
+ = render "layouts/search"
.fbtn
- if current_user.is_admin?
= link_to admin_root_path, class: "btn small", title: "Admin area" do
@@ -29,11 +27,3 @@
= link_to 'Logout', destroy_user_session_path, class: "logout", method: :delete
= render "layouts/init_auto_complete"
-
-:javascript
- $(function(){
- $("#search").autocomplete({
- source: #{raw search_autocomplete_source},
- select: function(event, ui) { location.href = ui.item.url }
- });
- });
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 87a74655..9eadc18c 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -1,11 +1,11 @@
:javascript
$(function() {
- autocompleteMembersUrl = "#{ "/api/v2/projects/#{@project.code}/members" if @project }";
- autocompleteMembersParams.private_token = "#{current_user.authentication_token}";
+ autocompleteMembers.url = "#{ "/api/v2/projects/#{@project.code}/members" if @project }";
+ autocompleteMembers.params.private_token = "#{current_user.private_token}";
- autocompleteEmojiData = #{raw emoji_autocomplete_source};
+ autocompleteEmoji.data = #{raw emoji_autocomplete_source};
// convert the list so that the items have the right format for completion
- autocompleteEmojiData = $.map(autocompleteEmojiData, function(value) {
+ autocompleteEmoji.data = $.map(autocompleteEmoji.data, function(value) {
return {
name: value,
insert: value+':',
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
new file mode 100644
index 00000000..80ecc530
--- /dev/null
+++ b/app/views/layouts/_search.html.haml
@@ -0,0 +1,11 @@
+.search
+ = form_tag search_path, method: :get do |f|
+ = text_field_tag "search", nil, placeholder: "Search", class: "search-input"
+
+:javascript
+ $(function(){
+ $("#search").autocomplete({
+ source: #{raw search_autocomplete_source},
+ select: function(event, ui) { location.href = ui.item.url }
+ });
+ });
diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml
index 30f88102..302e75cf 100644
--- a/app/views/merge_requests/_form.html.haml
+++ b/app/views/merge_requests/_form.html.haml
@@ -28,16 +28,22 @@
%h4.cdark 2. Fill info
.clearfix
- .main_box
+ .merge_requests_form_box
.top_box_content
- = f.label :title do
+ = f.label :title do
%strong= "Title *"
- .input= f.text_field :title, class: "input-xxlarge pad gfm-input", maxlength: 255, rows: 5
- .middle_box_content
- = f.label :assignee_id do
- %i.icon-user
- Assign to
- .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
+ .input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5
+ .merge_requests_middle_box
+ .merge_requests_assignee
+ = f.label :assignee_id do
+ %i.icon-user
+ Assign to
+ .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
+ .merge_requests_milestone
+ = f.label :milestone_id do
+ %i.icon-time
+ Milestone
+ .input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
.control-group
diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml
index 419419d2..4f68c5f2 100644
--- a/app/views/merge_requests/_merge_request.html.haml
+++ b/app/views/merge_requests/_merge_request.html.haml
@@ -10,6 +10,10 @@
%span.btn.small.disabled.grouped
%i.icon-comment
= merge_request.mr_and_commit_notes.count
+ - if merge_request.milestone_id?
+ %span.btn.small.disabled.grouped
+ %i.icon-time
+ = merge_request.milestone.title
%span.btn.small.disabled.grouped
= merge_request.source_branch
→
diff --git a/app/views/merge_requests/branch_from.js.haml b/app/views/merge_requests/branch_from.js.haml
index 156b4f0d..0637fdcb 100644
--- a/app/views/merge_requests/branch_from.js.haml
+++ b/app/views/merge_requests/branch_from.js.haml
@@ -1,2 +1,2 @@
:plain
- $(".mr_source_commit").html("#{escape_javascript(render 'commits/commit', commit: @commit)}");
+ $(".mr_source_commit").html("#{commit_to_html(@commit)}");
diff --git a/app/views/merge_requests/branch_to.js.haml b/app/views/merge_requests/branch_to.js.haml
index 8a201d42..974100d1 100644
--- a/app/views/merge_requests/branch_to.js.haml
+++ b/app/views/merge_requests/branch_to.js.haml
@@ -1,3 +1,2 @@
:plain
- $(".mr_target_commit").html("#{escape_javascript(render 'commits/commit', commit: @commit)}");
-
+ $(".mr_target_commit").html("#{commit_to_html(@commit)}");
diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml
index bbf35dc7..7bcb7a81 100644
--- a/app/views/merge_requests/index.html.haml
+++ b/app/views/merge_requests/index.html.haml
@@ -9,19 +9,26 @@
.ui-box
.title
- %ul.nav.nav-pills
- %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
- = link_to project_merge_requests_path(@project, f: 'open') do
- Open
- %li{class: ("active" if params[:f] == "closed")}
- = link_to project_merge_requests_path(@project, f: "closed") do
- Closed
- %li{class: ("active" if params[:f] == 'assigned-to-me')}
- = link_to project_merge_requests_path(@project, f: 'assigned-to-me') do
- To Me
- %li{class: ("active" if params[:f] == 'all')}
- = link_to project_merge_requests_path(@project, f: 'all') do
- All
+ .left
+ %ul.nav.nav-pills
+ %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
+ = link_to project_merge_requests_path(@project, f: 'open', milestone_id: params[:milestone_id]) do
+ Open
+ %li{class: ("active" if params[:f] == "closed")}
+ = link_to project_merge_requests_path(@project, f: "closed", milestone_id: params[:milestone_id]) do
+ Closed
+ %li{class: ("active" if params[:f] == 'assigned-to-me')}
+ = link_to project_merge_requests_path(@project, f: 'assigned-to-me', milestone_id: params[:milestone_id]) do
+ To Me
+ %li{class: ("active" if params[:f] == 'all')}
+ = link_to project_merge_requests_path(@project, f: 'all', milestone_id: params[:milestone_id]) do
+ All
+ .right
+ = form_tag project_merge_requests_path(@project), id: "merge_requests_search_form", method: :get, class: :right do
+ = select_tag(:assignee_id, options_from_collection_for_select([unassigned_filter] + @project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee")
+ = select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + @project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), prompt: "Milestone")
+ = hidden_field_tag :f, params[:f]
+ .clearfix
%ul.unstyled
= render @merge_requests
@@ -35,3 +42,7 @@
.span4.right
%span.cgray.right #{@merge_requests.total_count} merge requests for this filter
+:javascript
+ $(function() {
+ merge_requestsPage();
+ })
diff --git a/app/views/merge_requests/show/_mr_box.html.haml b/app/views/merge_requests/show/_mr_box.html.haml
index 89c3110b..26636435 100644
--- a/app/views/merge_requests/show/_mr_box.html.haml
+++ b/app/views/merge_requests/show/_mr_box.html.haml
@@ -14,9 +14,13 @@
%strong.author= link_to_merge_request_author(@merge_request)
- if @merge_request.assignee
- %cite.cgray and currently assigned to
+ %cite.cgray , currently assigned to
= image_tag gravatar_icon(@merge_request.assignee_email), width: 16, class: "lil_av"
%strong.author= link_to_merge_request_assignee(@merge_request)
+ - if @merge_request.milestone
+ - milestone = @merge_request.milestone
+ %cite.cgray and attached to milestone
+ %strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
- if @merge_request.closed
diff --git a/app/views/milestones/_milestone.html.haml b/app/views/milestones/_milestone.html.haml
index 205b864f..7c4c0e67 100644
--- a/app/views/milestones/_milestone.html.haml
+++ b/app/views/milestones/_milestone.html.haml
@@ -1,18 +1,22 @@
%li{class: "milestone", id: dom_id(milestone) }
.right
- - if milestone.issues.any?
- %span.btn.small.disabled.grouped= pluralize milestone.issues.count, 'issues'
- - if milestone.issues.count > 0
- = link_to 'Browse Issues', project_issues_path(milestone.project, milestone_id: milestone.id), class: "btn small grouped"
- if can? current_user, :admin_milestone, milestone.project
- = link_to 'Edit', edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped"
+ = link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
+ %i.icon-edit
+ Edit
%h4
- = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone), class: "row_title"
+ = link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
%small
= milestone.expires_at
- %br
- .progress.progress-success.span3
- .bar{style: "width: #{milestone.percent_complete}%;"}
-
-
-
+ .row
+ .span4
+ .progress.progress-info
+ .bar{style: "width: #{milestone.percent_complete}%;"}
+ .span6
+ = link_to project_issues_path(milestone.project, milestone_id: milestone.id) do
+ = pluralize milestone.issues.count, 'Issue'
+
+ = link_to project_merge_requests_path(milestone.project, milestone_id: milestone.id) do
+ = pluralize milestone.merge_requests.count, 'Merge Request'
+
+ %span.light #{milestone.percent_complete}% complete
diff --git a/app/views/milestones/show.html.haml b/app/views/milestones/show.html.haml
index c113c81f..b8bc788c 100644
--- a/app/views/milestones/show.html.haml
+++ b/app/views/milestones/show.html.haml
@@ -31,10 +31,10 @@
%h5
Progress:
%small
- #{@milestone.issues.closed.count} closed
+ #{@milestone.closed_items_count} closed
–
- #{@milestone.issues.opened.count} open
- .progress.progress-success
+ #{@milestone.open_items_count} open
+ .progress.progress-info
.bar{style: "width: #{@milestone.percent_complete}%;"}
@@ -58,15 +58,28 @@
%span.badge.badge-info ##{issue.id}
–
= link_to_gfm truncate(issue.title, length: 60), [@project, issue]
- %br
.span6
- %table
+ %table.milestone-merge-requests-filter
%thead
- %th Participants
- - @users.each do |user|
- %tr
+ %th
+ %ul.nav.nav-pills
+ %li.active= link_to('Open Merge Requests', '#')
+ %li=link_to('All Merge Requests', '#')
+ - @merge_requests.each do |merge_request|
+ %tr{data: {closed: merge_request.closed}}
%td
- = image_tag gravatar_icon(user.email, 24), width: "24"
-
- = user.name
+ = link_to [@project, merge_request] do
+ %span.badge.badge-info ##{merge_request.id}
+ –
+ = link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request]
+
+%hr
+%h6 Participants:
+%div
+ - @users.each do |user|
+ = link_to tm_path(user.tm_of(@project)), class: 'float-link' do
+ = user.avatar_image
+ = user.name
+
+.clearfix
diff --git a/app/views/notes/_common_form.html.haml b/app/views/notes/_common_form.html.haml
index a9f2907b..0725082d 100644
--- a/app/views/notes/_common_form.html.haml
+++ b/app/views/notes/_common_form.html.haml
@@ -8,7 +8,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
- = f.text_area :note, size: 255, class: 'note-text gfm-input'
+ = f.text_area :note, size: 255, class: 'note-text js-gfm-input'
#preview-note.preview_note.hide
.hint
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml
index ee0cde4b..c8d79850 100644
--- a/app/views/notes/_per_line_form.html.haml
+++ b/app/views/notes/_per_line_form.html.haml
@@ -13,7 +13,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
= f.hidden_field :line_code
- = f.text_area :note, size: 255, class: 'line-note-text gfm-input'
+ = f.text_area :note, size: 255, class: 'line-note-text js-gfm-input'
.note_actions
.buttons
= f.submit 'Add note', class: "btn save-btn submit_note submit_inline_note", id: "submit_note"
diff --git a/app/views/notify/project_access_granted_email.html.haml b/app/views/notify/project_access_granted_email.html.haml
index 154c2aaa..72b3f065 100644
--- a/app/views/notify/project_access_granted_email.html.haml
+++ b/app/views/notify/project_access_granted_email.html.haml
@@ -4,7 +4,7 @@
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}
%td{align: "left", style: "padding: 20px 0 0;"}
%h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
- = "You got granted #{@users_project.project_access_human} access to project"
+ = "You have been granted #{@users_project.project_access_human} access to project"
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}
%tr
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}
diff --git a/app/views/profile/account.html.haml b/app/views/profile/account.html.haml
index 6707a8ff..112963cc 100644
--- a/app/views/profile/account.html.haml
+++ b/app/views/profile/account.html.haml
@@ -14,7 +14,7 @@
%h3.page_title
Private token
%span.cred.right
- keep it in secret!
+ keep it secret!
.padded
= form_for @user, url: profile_reset_private_token_path, method: :put do |f|
.data
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 4411ff17..aa1a9cdc 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -1,11 +1,7 @@
.project_clone_panel
.row
.span7
- .form-horizontal
- .input-prepend.project_clone_holder
- %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
- %button{class: "btn small", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.web_protocol.upcase
- = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
+ .form-horizontal= render "shared/clone_panel"
.span4.right
.right
- unless @project.empty_repo?
diff --git a/app/views/projects/graph.html.haml b/app/views/projects/graph.html.haml
index 76ada998..07f038d2 100644
--- a/app/views/projects/graph.html.haml
+++ b/app/views/projects/graph.html.haml
@@ -10,5 +10,5 @@
initGraph();
$(function(){
branchGraph($("#holder")[0]);
- initGraphNav();
+ GraphNav.init();
});
diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml
index 3c1fe47c..2728b100 100644
--- a/app/views/repositories/_branch.html.haml
+++ b/app/views/repositories/_branch.html.haml
@@ -3,19 +3,25 @@
%tr
%td
= link_to project_commits_path(@project, branch.name) do
+ - if @project.protected_branch? branch.name
+ %i.icon-lock
+ - else
+ %i.icon-unlock
%strong= truncate(branch.name, length: 60)
- if branch.name == @project.root_ref
%span.label default
%td
- = link_to project_commit_path(@project, commit) do
- %code= commit.short_id
-
- = image_tag gravatar_icon(commit.author_email), class: "", width: 16
- = gfm escape_once(truncate(commit.title, length: 40))
- %span.update-author.right
+ = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
+ = commit.short_id
+ = image_tag gravatar_icon(commit.author_email), class: "avatar s16"
+ %span.light
+ = gfm escape_once(truncate(commit.title, length: 40))
+ %span
= time_ago_in_words(commit.committed_date)
ago
%td
- if can? current_user, :download_code, @project
- = link_to "Download", archive_project_repository_path(@project, ref: branch.name), class: "visible_link download_repo_link"
+ = link_to archive_project_repository_path(@project, ref: branch.name) do
+ %i.icon-download
+ Download
diff --git a/app/views/repositories/_branches_head.html.haml b/app/views/repositories/_branches_head.html.haml
index 25a988cf..8f3e1ba3 100644
--- a/app/views/repositories/_branches_head.html.haml
+++ b/app/views/repositories/_branches_head.html.haml
@@ -3,6 +3,8 @@
= nav_link(path: 'repositories#show') do
= link_to 'Recent', project_repository_path(@project)
= nav_link(path: 'protected_branches#index') do
- = link_to 'Protected', project_protected_branches_path(@project)
+ = link_to project_protected_branches_path(@project) do
+ %i.icon-lock
+ Protected
= nav_link(path: 'repositories#branches') do
= link_to 'All', branches_project_repository_path(@project)
diff --git a/app/views/repositories/stats.html.haml b/app/views/repositories/stats.html.haml
new file mode 100644
index 00000000..a0a9377d
--- /dev/null
+++ b/app/views/repositories/stats.html.haml
@@ -0,0 +1,39 @@
+= render "commits/head"
+.row
+ .span5
+ %h4
+ Stats for #{@project.root_ref}:
+ %p
+ %b Total commits:
+ %span= @stats.commits_count
+ %p
+ %b Total files:
+ %span= @stats.files_count
+ %p
+ %b Authors:
+ %span= @stats.authors_count
+
+ %br
+ %div#activity-chart
+ .span7
+ %h4 Top 50 Committers:
+ %ol.styled
+ - @stats.authors[0...50].each do |author|
+ %li
+ = image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
+ = author.name
+ %small.light= author.email
+ .right
+ = author.commits
+
+
+:javascript
+ $(function(){
+ var labels = [#{@graph.labels.to_json}];
+ var r = Raphael('activity-chart');
+ r.text(160, 10, "Commit activity for last #{@graph.weeks} weeks").attr({ font: "13px sans-serif" });
+ r.barchart(
+ 10, 10, 400, 160,
+ [[#{@graph.commits.join(', ')}]]
+ ).label(labels, true);
+ })
diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml
index 38cc3aca..193cb2e3 100644
--- a/app/views/repositories/tags.html.haml
+++ b/app/views/repositories/tags.html.haml
@@ -5,27 +5,29 @@
%tr
%th Name
%th Last commit
- %th Updated at
%th
- @tags.each do |tag|
- commit = Commit.new(tag.commit)
- commit = CommitDecorator.decorate(commit)
%tr
%td
- %strong= link_to tag.name, project_commits_path(@project, tag.name), class: ""
+ %strong
+ = link_to project_commits_path(@project, tag.name), class: "" do
+ %i.icon-tag
+ = tag.name
+ %small.light= truncate(tag.message || '', length: 70)
%td
- = link_to project_commit_path(@project, commit.id) do
- %code= commit.short_id
- = image_tag gravatar_icon(commit.author_email), class: "", width: 16
- = gfm escape_once(truncate(commit.title, length: 40))
- %td
- %span.update-author.right
+ = image_tag gravatar_icon(commit.author_email), class: "avatar s16"
+ = link_to project_commit_path(@project, commit.id), class: 'commit_short_id' do
+ = commit.short_id
+ %span.light
= time_ago_in_words(commit.committed_date)
ago
-
%td
- if can? current_user, :download_code, @project
- = link_to "Download", archive_project_repository_path(@project, ref: tag.name), class: "visible_link download_repo_link"
+ = link_to archive_project_repository_path(@project, ref: tag.name) do
+ %i.icon-download
+ Download
- else
%h3 No tags
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index d85c24ec..0d5f5458 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -9,7 +9,7 @@
%br
%h3
Search results
- %small (#{@projects.count + @merge_requests.count + @issues.count})
+ %small (#{@projects.count + @merge_requests.count + @issues.count + @wiki_pages.count})
%hr
.search_results
.row
@@ -69,6 +69,23 @@
%tr
%td
%h4.nothing_here_message No Issues
+ .span6
+ %table
+ %thead
+ %tr
+ %th Wiki
+ %tbody
+ - @wiki_pages.each do |wiki_page|
+ %tr
+ %td
+ = link_to project_wiki_path(wiki_page.project, wiki_page) do
+ %strong.term= truncate wiki_page.title, length: 40
+ %strong.right
+ %span.label= wiki_page.project.name
+ - if @wiki_pages.blank?
+ %tr
+ %td
+ %h4.nothing_here_message No wiki pages
:javascript
$(function() {
$(".search_results .term").highlight("#{params[:search]}");
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
new file mode 100644
index 00000000..947dc478
--- /dev/null
+++ b/app/views/shared/_clone_panel.html.haml
@@ -0,0 +1,4 @@
+.input-prepend.project_clone_holder
+ %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
+ %button{class: "btn small", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.web_protocol.upcase
+ = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index b6ab666b..a11f2bc4 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -1,8 +1,8 @@
- if current_user.require_ssh_key?
%h6.error_message
%span
- You wont be able to pull/push project code unless you
+ You won't be able to pull or push project code until you
%strong
= link_to new_key_path, class: "vlink" do
- add SSH key
+ add an SSH key
to your profile
diff --git a/app/views/tree/_blob.html.haml b/app/views/tree/_blob.html.haml
index 9ede3f8e..ebf1ee2c 100644
--- a/app/views/tree/_blob.html.haml
+++ b/app/views/tree/_blob.html.haml
@@ -2,7 +2,7 @@
.file_title
%i.icon-file
%span.file_name
- = blob.name.force_encoding('utf-8')
+ = blob.name
%small= number_to_human_size blob.size
%span.options= render "tree/blob_actions"
- if blob.text?
diff --git a/app/views/tree/_head.html.haml b/app/views/tree/_head.html.haml
index f1b3f63f..f8e5c99f 100644
--- a/app/views/tree/_head.html.haml
+++ b/app/views/tree/_head.html.haml
@@ -4,7 +4,4 @@
= nav_link(controller: :tree) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.right
- .input-prepend.project_clone_holder
- %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
- %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP
- = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
+ = render "shared/clone_panel"
\ No newline at end of file
diff --git a/app/views/tree/_submodule_item.html.haml b/app/views/tree/_submodule_item.html.haml
index 43fa7f24..b0562fe1 100644
--- a/app/views/tree/_submodule_item.html.haml
+++ b/app/views/tree/_submodule_item.html.haml
@@ -1,4 +1,4 @@
-- url = submodule_item.url(@ref) rescue nil
+- url = submodule_item.url(@ref) rescue ''
- name = submodule_item.basename
- return unless url
%tr{ class: "tree-item", url: url }
diff --git a/app/views/tree/blob/_text.html.haml b/app/views/tree/blob/_text.html.haml
index c506a39f..3b7f293a 100644
--- a/app/views/tree/blob/_text.html.haml
+++ b/app/views/tree/blob/_text.html.haml
@@ -10,6 +10,6 @@
- unless blob.empty?
%div{class: current_user.dark_scheme ? "black" : "white"}
= preserve do
- = raw blob.colorize(options: { linenos: 'True'})
+ = raw blob.colorize(options: { linenos: true, lineanchors: :line, anchorlinenos: true })
- else
%h4.nothing_here_message Empty file
diff --git a/app/views/tree/edit.html.haml b/app/views/tree/edit.html.haml
index fdd334a3..a14a15b0 100644
--- a/app/views/tree/edit.html.haml
+++ b/app/views/tree/edit.html.haml
@@ -4,7 +4,7 @@
.file_title
%i.icon-file
%span.file_name
- = "#{@tree.path.force_encoding('utf-8')} (#{@ref})"
+ = "#{@tree.path} (#{@ref})"
.file_content.code
#editor= @tree.data
diff --git a/app/views/wikis/_form.html.haml b/app/views/wikis/_form.html.haml
index 89bbe2ea..83b16b13 100644
--- a/app/views/wikis/_form.html.haml
+++ b/app/views/wikis/_form.html.haml
@@ -21,7 +21,7 @@
.bottom_box_content
= f.label :content
- .input= f.text_area :content, class: 'span8 gfm-input'
+ .input= f.text_area :content, class: 'span8 js-gfm-input'
.actions
= f.submit 'Save', class: "save-btn btn"
= link_to "Cancel", project_wiki_path(@project, :index), class: "btn cancel-btn"
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 28323484..35683489 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -74,6 +74,7 @@ git_host:
upload_pack: true
receive_pack: true
# host: localhost
+ # config_file: gitolite.conf
# port: 22
# Git settings
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index fb809636..32af3d07 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -104,6 +104,10 @@ class Settings < Settingslogic
git_host['admin_uri'] || 'git@localhost:gitolite-admin'
end
+ def gitolite_config_file
+ git_host['config_file'] || 'gitolite.conf'
+ end
+
def gitolite_admin_key
git_host['gitolite_admin_key'] || 'gitlab'
end
diff --git a/config/initializers/3_grit_ext.rb b/config/initializers/3_grit_ext.rb
index fd7e288a..d114ea6c 100644
--- a/config/initializers/3_grit_ext.rb
+++ b/config/initializers/3_grit_ext.rb
@@ -6,23 +6,4 @@ Grit::Git.git_max_size = Gitlab.config.git_max_size
Grit::Blob.class_eval do
include Linguist::BlobHelper
-
- def data
- @data ||= @repo.git.cat_file({:p => true}, id)
- Gitlab::Encode.utf8 @data
- end
-end
-
-Grit::Diff.class_eval do
- def old_path
- Gitlab::Encode.utf8 @a_path
- end
-
- def new_path
- Gitlab::Encode.utf8 @b_path
- end
-
- def diff
- Gitlab::Encode.utf8 @diff
- end
end
diff --git a/config/initializers/quite_assets.rb b/config/initializers/quite_assets.rb
deleted file mode 100644
index 6fed1803..00000000
--- a/config/initializers/quite_assets.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-if Rails.env.development?
- Rails.application.assets.logger = Logger.new('/dev/null')
- Rails::Rack::Logger.class_eval do
- def call_with_quiet_assets(env)
- previous_level = Rails.logger.level
- Rails.logger.level = Logger::ERROR if env['PATH_INFO'] =~ %r{^/assets/}
- call_without_quiet_assets(env)
- ensure
- Rails.logger.level = previous_level
- end
- alias_method_chain :call, :quiet_assets
- end
-end
diff --git a/config/routes.rb b/config/routes.rb
index adaf6a1e..bf762865 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -18,7 +18,7 @@ Gitlab::Application.routes.draw do
project_root: Gitlab.config.git_base_path,
upload_pack: Gitlab.config.git_upload_pack,
receive_pack: Gitlab.config.git_receive_pack
- }), at: '/:path', constraints: { path: /[\w-]+\.git/ }
+ }), at: '/:path', constraints: { path: /[\w\.-]+\.git/ }
#
# Help
@@ -128,6 +128,7 @@ Gitlab::Application.routes.draw do
member do
get "branches"
get "tags"
+ get "stats"
get "archive"
end
end
diff --git a/db/fixtures/development/005_issues.rb b/db/fixtures/development/005_issues.rb
deleted file mode 100644
index 32375387..00000000
--- a/db/fixtures/development/005_issues.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-Issue.seed(:id, [
- { :id => 1, :project_id => 1, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
- { :id => 2, :project_id => 1, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
- { :id => 3, :project_id => 1, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
- { :id => 4, :project_id => 1, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
- { :id => 5, :project_id => 1, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
-
- { :id => 6, :project_id => 2, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
- { :id => 7, :project_id => 2, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
- { :id => 8, :project_id => 2, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
- { :id => 9, :project_id => 2, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
- { :id => 11, :project_id => 2, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
-
- { :id => 12, :project_id => 3, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6)},
- { :id => 13, :project_id => 3, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6)},
- { :id => 14, :project_id => 3, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6)},
- { :id => 15, :project_id => 3, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6)},
- { :id => 16, :project_id => 3, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6)},
-
- { :id => 21, :project_id => 1, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
- { :id => 22, :project_id => 1, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
- { :id => 23, :project_id => 1, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
- { :id => 24, :project_id => 1, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
- { :id => 25, :project_id => 1, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
-
- { :id => 26, :project_id => 2, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6) },
- { :id => 27, :project_id => 2, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6) },
- { :id => 28, :project_id => 2, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6) },
- { :id => 29, :project_id => 2, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6) },
- { :id => 30, :project_id => 2, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6) },
-
- { :id => 32, :project_id => 3, :author_id => 1, :assignee_id => 1, :title => Faker::Lorem.sentence(6)},
- { :id => 33, :project_id => 3, :author_id => 2, :assignee_id => 2, :title => Faker::Lorem.sentence(6)},
- { :id => 34, :project_id => 3, :author_id => 3, :assignee_id => 3, :title => Faker::Lorem.sentence(6)},
- { :id => 35, :project_id => 3, :author_id => 4, :assignee_id => 4, :title => Faker::Lorem.sentence(6)},
- { :id => 36, :project_id => 3, :author_id => 5, :assignee_id => 5, :title => Faker::Lorem.sentence(6)}
-])
-
-
-
diff --git a/db/fixtures/development/005_milestones.rb b/db/fixtures/development/005_milestones.rb
new file mode 100644
index 00000000..a77f619f
--- /dev/null
+++ b/db/fixtures/development/005_milestones.rb
@@ -0,0 +1,13 @@
+Milestone.seed(:id, [
+ { :id => 1, :project_id => 1, :title => 'v' + Faker::Address.zip_code },
+ { :id => 2, :project_id => 1, :title => 'v' + Faker::Address.zip_code },
+ { :id => 3, :project_id => 1, :title => 'v' + Faker::Address.zip_code },
+ { :id => 4, :project_id => 2, :title => 'v' + Faker::Address.zip_code },
+ { :id => 5, :project_id => 2, :title => 'v' + Faker::Address.zip_code },
+
+ { :id => 6, :project_id => 2, :title => 'v' + Faker::Address.zip_code },
+ { :id => 7, :project_id => 2, :title => 'v' + Faker::Address.zip_code },
+ { :id => 8, :project_id => 3, :title => 'v' + Faker::Address.zip_code },
+ { :id => 9, :project_id => 3, :title => 'v' + Faker::Address.zip_code },
+ { :id => 11, :project_id => 3, :title => 'v' + Faker::Address.zip_code },
+])
diff --git a/db/fixtures/development/007_issues.rb b/db/fixtures/development/007_issues.rb
new file mode 100644
index 00000000..d60af71e
--- /dev/null
+++ b/db/fixtures/development/007_issues.rb
@@ -0,0 +1,20 @@
+(1..300).each do |i|
+ # Random Project
+ project_id = rand(2) + 1
+ project = Project.find(project_id)
+
+ # Random user
+ user = project.users.sample
+ user_id = user.id
+ IssueObserver.current_user = user
+
+ Issue.seed(:id, [{
+ id: i,
+ project_id: project_id,
+ author_id: user_id,
+ assignee_id: user_id,
+ closed: [true, false].sample,
+ milestone: project.milestones.sample,
+ title: Faker::Lorem.sentence(6)
+ }])
+end
diff --git a/db/fixtures/development/008_merge_requests.rb b/db/fixtures/development/008_merge_requests.rb
new file mode 100644
index 00000000..8d20e628
--- /dev/null
+++ b/db/fixtures/development/008_merge_requests.rb
@@ -0,0 +1,22 @@
+(1..300).each do |i|
+ # Random Project
+ project_id = rand(2) + 1
+ project = Project.find(project_id)
+
+ # Random user
+ user = project.users.sample
+ user_id = user.id
+ MergeRequestObserver.current_user = user
+
+ MergeRequest.seed(:id, [{
+ id: i,
+ source_branch: 'master',
+ target_branch: 'feature',
+ project_id: project_id,
+ author_id: user_id,
+ assignee_id: user_id,
+ closed: [true, false].sample,
+ milestone: project.milestones.sample,
+ title: Faker::Lorem.sentence(6)
+ }])
+end
diff --git a/db/migrate/20121026114600_add_milestone_id_to_merge_requests.rb b/db/migrate/20121026114600_add_milestone_id_to_merge_requests.rb
new file mode 100644
index 00000000..b5167724
--- /dev/null
+++ b/db/migrate/20121026114600_add_milestone_id_to_merge_requests.rb
@@ -0,0 +1,5 @@
+class AddMilestoneIdToMergeRequests < ActiveRecord::Migration
+ def change
+ add_column :merge_requests, :milestone_id, :integer, :null => true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a7037811..e7eb5696 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20121009205010) do
+ActiveRecord::Schema.define(:version => 20121026114600) do
create_table "events", :force => true do |t|
t.string "target_type"
@@ -73,6 +73,7 @@ ActiveRecord::Schema.define(:version => 20121009205010) do
t.text "st_diffs", :limit => 2147483647
t.boolean "merged", :default => false, :null => false
t.integer "state", :default => 1, :null => false
+ t.integer "milestone_id"
end
add_index "merge_requests", ["project_id"], :name => "index_merge_requests_on_project_id"
@@ -155,30 +156,30 @@ ActiveRecord::Schema.define(:version => 20121009205010) do
end
create_table "users", :force => true do |t|
- t.string "email", :default => "", :null => false
- t.string "encrypted_password", :limit => 128, :default => "", :null => false
+ t.string "email", :default => "", :null => false
+ t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
- t.integer "sign_in_count", :default => 0
+ t.integer "sign_in_count", :default => 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
t.string "name"
- t.boolean "admin", :default => false, :null => false
- t.integer "projects_limit", :default => 10
- t.string "skype", :default => "", :null => false
- t.string "linkedin", :default => "", :null => false
- t.string "twitter", :default => "", :null => false
+ t.boolean "admin", :default => false, :null => false
+ t.integer "projects_limit", :default => 10
+ t.string "skype", :default => "", :null => false
+ t.string "linkedin", :default => "", :null => false
+ t.string "twitter", :default => "", :null => false
t.string "authentication_token"
- t.boolean "dark_scheme", :default => false, :null => false
- t.integer "theme_id", :default => 1, :null => false
+ t.boolean "dark_scheme", :default => false, :null => false
+ t.integer "theme_id", :default => 1, :null => false
t.string "bio"
- t.boolean "blocked", :default => false, :null => false
- t.integer "failed_attempts", :default => 0
+ t.boolean "blocked", :default => false, :null => false
+ t.integer "failed_attempts", :default => 0
t.datetime "locked_at"
t.string "extern_uid"
t.string "provider"
diff --git a/doc/README_FOR_APP b/doc/README_FOR_APP
deleted file mode 100644
index fe41f5cc..00000000
--- a/doc/README_FOR_APP
+++ /dev/null
@@ -1,2 +0,0 @@
-Use this README file to introduce your application and point to useful places in the API for learning more.
-Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
new file mode 100644
index 00000000..e5b067a6
--- /dev/null
+++ b/doc/api/merge_requests.md
@@ -0,0 +1,194 @@
+## List merge requests
+
+Get all MR for this project.
+
+```
+GET /projects/:id/merge_requests
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
+
+```json
+[
+ {
+ "id":1,
+ "target_branch":"master",
+ "source_branch":"test1",
+ "project_id":3,
+ "title":"test1",
+ "closed":true,
+ "merged":false,
+ "author":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ },
+ "assignee":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ }
+ }
+]
+```
+
+## Show MR
+
+Show information about MR.
+
+```
+GET /projects/:id/merge_request/:merge_request_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `merge_request_id` (required) - The ID of MR
+
+```json
+{
+ "id":1,
+ "target_branch":"master",
+ "source_branch":"test1",
+ "project_id":3,
+ "title":"test1",
+ "closed":true,
+ "merged":false,
+ "author":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ },
+ "assignee":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ }
+}
+```
+
+
+## Create MR
+
+Create MR.
+
+```
+POST /projects/:id/merge_requests
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `source_branch` (required) - The source branch
++ `target_branch` (required) - The target branch
++ `assignee_id` - Assignee user ID
++ `title` (required) - Title of MR
+
+```json
+{
+ "id":1,
+ "target_branch":"master",
+ "source_branch":"test1",
+ "project_id":3,
+ "title":"test1",
+ "closed":true,
+ "merged":false,
+ "author":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ },
+ "assignee":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ }
+}
+```
+
+## Update MR
+
+Update MR. You can change branches, title, or even close the MR.
+
+```
+PUT /projects/:id/merge_request/:merge_request_id
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `merge_request_id` (required) - ID of MR
++ `source_branch` - The source branch
++ `target_branch` - The target branch
++ `assignee_id` - Assignee user ID
++ `title` - Title of MR
++ `closed` - Status of MR. true - closed
+
+
+```json
+{
+ "id":1,
+ "target_branch":"master",
+ "source_branch":"test1",
+ "project_id":3,
+ "title":"test1",
+ "closed":true,
+ "merged":false,
+ "author":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ },
+ "assignee":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ }
+}
+```
+## Post comment to MR
+
+Post comment to MR
+
+```
+POST /projects/:id/merge_request/:merge_request_id/comments
+```
+
+Parameters:
+
++ `id` (required) - The ID or code name of a project
++ `merge_request_id` (required) - ID of MR
++ `note` (required) - Text of comment
+
+Will return created note with status `201 Created` on success, or `404 Not found` on fail.
+
+```json
+{
+ "author":{
+ "id":1,
+ "email":"admin@local.host",
+ "name":"Administrator",
+ "blocked":false,
+ "created_at":"2012-04-29T08:46:00Z"
+ },
+ "note":"text1"
+}
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index 63271ee8..c116144d 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -74,14 +74,12 @@ POST /users
Parameters:
+ `email` (required) - Email
-+ `name` (required) - Name
+ `password` (required) - Password
-+ `password_confirmation` (required) - Password confirmation
++ `name` - Name
+ `skype` - Skype ID
+ `linkedin` - Linkedin
+ `twitter` - Twitter account
-+ `projects_limit` - Limit projects wich user can create
-
++ `projects_limit` - Number of projects user can create
Will return created user with status `201 Created` on success, or `404 Not
found` on fail.
diff --git a/doc/app/Ability.html b/doc/app/Ability.html
new file mode 100644
index 00000000..f780d067
--- /dev/null
+++ b/doc/app/Ability.html
@@ -0,0 +1,570 @@
+
+
+
+
+
+
+class Ability - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Ability
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ allowed (object, subject)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def allowed (object , subject )
+ case subject .class .name
+ when "Project" then project_abilities (object , subject )
+ when "Issue" then issue_abilities (object , subject )
+ when "Note" then note_abilities (object , subject )
+ when "Snippet" then snippet_abilities (object , subject )
+ when "MergeRequest" then merge_request_abilities (object , subject )
+ else []
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_abilities (user, project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_abilities (user , project )
+ rules = []
+
+ rules << [
+ :read_project ,
+ :read_wiki ,
+ :read_issue ,
+ :read_milestone ,
+ :read_snippet ,
+ :read_team_member ,
+ :read_merge_request ,
+ :read_note ,
+ :write_project ,
+ :write_issue ,
+ :write_note
+ ] if project .guest_access_for? (user )
+
+ rules << [
+ :download_code ,
+ :write_merge_request ,
+ :write_snippet
+ ] if project .report_access_for? (user )
+
+ rules << [
+ :write_wiki ,
+ :push_code
+ ] if project .dev_access_for? (user )
+
+ rules << [
+ :push_code_to_protected_branches
+ ] if project .master_access_for? (user )
+
+ rules << [
+ :modify_issue ,
+ :modify_snippet ,
+ :modify_merge_request ,
+ :admin_project ,
+ :admin_issue ,
+ :admin_milestone ,
+ :admin_snippet ,
+ :admin_team_member ,
+ :admin_merge_request ,
+ :admin_note ,
+ :accept_mr ,
+ :admin_wiki
+ ] if project .master_access_for? (user ) || project .owner == user
+
+ rules .flatten
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Account.html b/doc/app/Account.html
new file mode 100644
index 00000000..58f65758
--- /dev/null
+++ b/doc/app/Account.html
@@ -0,0 +1,881 @@
+
+
+
+
+
+
+module Account - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Account
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ block ()
+ click to toggle source
+
+
+
+
+
+
Remove user from all projects and set blocked attribute to true
+
+
+
+
+
+def block
+ users_projects .find_each do | membership |
+ return false unless membership .destroy
+ end
+
+ self .blocked = true
+ save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can_create_group? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can_create_group?
+ is_admin?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can_create_project? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can_create_project?
+ projects_limit > my_own_projects .count
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cared_merge_requests ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def cared_merge_requests
+ MergeRequest .where ("author_id = :id or assignee_id = :id" , id : self .id ).opened
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ first_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def first_name
+ name .split .first unless name .blank?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ identifier ()
+ click to toggle source
+
+
+
+
+
+
Returns a string for use as a Gitolite user identifier
+
+
Note that Gitolite 2.x requires the following
+pattern for users:
+
+
^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
+
+
+
+
+
+def identifier
+
+
+ email .gsub (%r\W/ , '_' ).gsub (%r\A([\W\_])+/ , '' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_admin? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_admin?
+ admin
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_activity_project ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_activity_project
+ projects .first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_ids ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_ids
+ projects .map (&:id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ projects_limit_percent ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def projects_limit_percent
+ return 100 if projects_limit .zero?
+ (my_own_projects .count .to_f / projects_limit ) * 100
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ projects_with_events ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def projects_with_events
+ projects .includes (:events ).order ("events.created_at DESC" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ recent_push (project_id = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def recent_push project_id = nil
+
+ events = recent_events .code_push .where ("created_at > ?" , Time .now - 2 .hours )
+ events = events .where (project_id : project_id ) if project_id
+
+
+ events = events .recent .limit (1 ).first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ require_ssh_key? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def require_ssh_key?
+ keys .count == 0
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ActivityObserver.html b/doc/app/ActivityObserver.html
new file mode 100644
index 00000000..3b31271d
--- /dev/null
+++ b/doc/app/ActivityObserver.html
@@ -0,0 +1,531 @@
+
+
+
+
+
+
+class ActivityObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ActivityObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (record)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (record )
+ Event .create (
+ project : record .project ,
+ target_id : record .id ,
+ target_type : record .class .name ,
+ action : Event .determine_action (record ),
+ author_id : record .author_id
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_save (record)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_save (record )
+ if record .changed .include? ("closed" )
+ Event .create (
+ project : record .project ,
+ target_id : record .id ,
+ target_type : record .class .name ,
+ action : (record .closed ? Event :: Closed : Event :: Reopened ),
+ author_id : record .author_id_of_changes
+ )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin.html b/doc/app/Admin.html
new file mode 100644
index 00000000..94fb27ef
--- /dev/null
+++ b/doc/app/Admin.html
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+module Admin - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Admin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/DashboardController.html b/doc/app/Admin/DashboardController.html
new file mode 100644
index 00000000..00154b3d
--- /dev/null
+++ b/doc/app/Admin/DashboardController.html
@@ -0,0 +1,488 @@
+
+
+
+
+
+
+class Admin::DashboardController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::DashboardController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @workers = Resque .workers
+ @pending_jobs = Resque .size (:post_receive )
+ @projects = Project .order ("created_at DESC" ).limit (10 )
+ @users = User .order ("created_at DESC" ).limit (10 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/GroupsController.html b/doc/app/Admin/GroupsController.html
new file mode 100644
index 00000000..ef4dae9e
--- /dev/null
+++ b/doc/app/Admin/GroupsController.html
@@ -0,0 +1,771 @@
+
+
+
+
+
+
+class Admin::GroupsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::GroupsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @group = Group .new (params [:group ])
+ @group .owner = current_user
+
+ if @group .save
+ redirect_to [:admin , @group ], notice : 'Group was successfully created.'
+ else
+ render action : "new"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @group .destroy
+
+ redirect_to admin_groups_path , notice : 'Group was successfully deleted.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @groups = Group .scoped
+ @groups = @groups .search (params [:name ]) if params [:name ].present?
+ @groups = @groups .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @group = Group .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_update
+ project_ids = params [:project_ids ]
+ Project .where (id : project_ids ).update_all (group_id : @group .id )
+
+ redirect_to :back , notice : 'Group was successfully updated.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ remove_project ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def remove_project
+ @project = Project .find (params [:project_id ])
+ @project .group_id = nil
+ @project .save
+
+ redirect_to :back , notice : 'Group was successfully updated.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @projects = Project .scoped
+ @projects = @projects .not_in_group (@group ) if @group .projects .present?
+ @projects = @projects .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ group_params = params [:group ].dup
+ owner_id =group_params .delete (:owner_id )
+
+ if owner_id
+ @group .owner = User .find (owner_id )
+ end
+
+ if @group .update_attributes (group_params )
+ redirect_to [:admin , @group ], notice : 'Group was successfully updated.'
+ else
+ render action : "edit"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/HooksController.html b/doc/app/Admin/HooksController.html
new file mode 100644
index 00000000..48cd5d00
--- /dev/null
+++ b/doc/app/Admin/HooksController.html
@@ -0,0 +1,603 @@
+
+
+
+
+
+
+class Admin::HooksController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::HooksController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @hook = SystemHook .new (params [:hook ])
+
+ if @hook .save
+ redirect_to admin_hooks_path , notice : 'Hook was successfully created.'
+ else
+ @hooks = SystemHook .all
+ render :index
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @hook = SystemHook .find (params [:id ])
+ @hook .destroy
+
+ redirect_to admin_hooks_path
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @hooks = SystemHook .all
+ @hook = SystemHook .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def test
+ @hook = SystemHook .find (params [:hook_id ])
+ data = {
+ event_name : "project_create" ,
+ name : "Ruby" ,
+ path : "ruby" ,
+ project_id : 1 ,
+ owner_name : "Someone" ,
+ owner_email : "example@gitlabhq.com"
+ }
+ @hook .execute (data )
+
+ redirect_to :back
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/LogsController.html b/doc/app/Admin/LogsController.html
new file mode 100644
index 00000000..8f70b1ad
--- /dev/null
+++ b/doc/app/Admin/LogsController.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Admin::LogsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::LogsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/ProjectsController.html b/doc/app/Admin/ProjectsController.html
new file mode 100644
index 00000000..5744746b
--- /dev/null
+++ b/doc/app/Admin/ProjectsController.html
@@ -0,0 +1,733 @@
+
+
+
+
+
+
+class Admin::ProjectsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::ProjectsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @admin_project = Project .new (params [:project ])
+ @admin_project .owner = current_user
+
+ if @admin_project .save
+ redirect_to [:admin , @admin_project ], notice : 'Project was successfully created.'
+ else
+ render action : "new"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @admin_project .destroy
+
+ redirect_to admin_projects_url , notice : 'Project was successfully deleted.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @admin_projects = Project .scoped
+ @admin_projects = @admin_projects .search (params [:name ]) if params [:name ].present?
+ @admin_projects = @admin_projects .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @admin_project = Project .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @users = User .scoped
+ @users = @users .not_in_project (@admin_project ) if @admin_project .users .present?
+ @users = @users .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ team_update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def team_update
+ @admin_project .add_users_ids_to_team (params [:user_ids ], params [:project_access ])
+
+ redirect_to [:admin , @admin_project ], notice : 'Project was successfully updated.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ owner_id = params [:project ].delete (:owner_id )
+
+ if owner_id
+ @admin_project .owner = User .find (owner_id )
+ end
+
+ if @admin_project .update_attributes (params [:project ])
+ redirect_to [:admin , @admin_project ], notice : 'Project was successfully updated.'
+ else
+ render action : "edit"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/ResqueController.html b/doc/app/Admin/ResqueController.html
new file mode 100644
index 00000000..db73599b
--- /dev/null
+++ b/doc/app/Admin/ResqueController.html
@@ -0,0 +1,484 @@
+
+
+
+
+
+
+class Admin::ResqueController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::ResqueController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/TeamMembersController.html b/doc/app/Admin/TeamMembersController.html
new file mode 100644
index 00000000..907bf279
--- /dev/null
+++ b/doc/app/Admin/TeamMembersController.html
@@ -0,0 +1,558 @@
+
+
+
+
+
+
+class Admin::TeamMembersController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::TeamMembersController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @admin_team_member = UsersProject .find (params [:id ])
+ @admin_team_member .destroy
+
+ redirect_to :back
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ @admin_team_member = UsersProject .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @admin_team_member = UsersProject .find (params [:id ])
+
+ if @admin_team_member .update_attributes (params [:team_member ])
+ redirect_to [:admin , @admin_team_member .project ], notice : 'Project Access was successfully updated.'
+ else
+ render action : "edit"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Admin/UsersController.html b/doc/app/Admin/UsersController.html
new file mode 100644
index 00000000..b300e4f7
--- /dev/null
+++ b/doc/app/Admin/UsersController.html
@@ -0,0 +1,839 @@
+
+
+
+
+
+
+class Admin::UsersController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Admin::UsersController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ block ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def block
+ @admin_user = User .find (params [:id ])
+
+ if @admin_user .block
+ redirect_to :back , alert : "Successfully blocked"
+ else
+ redirect_to :back , alert : "Error occured. User was not blocked"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ admin = params [:user ].delete ("admin" )
+
+ @admin_user = User .new (params [:user ], as : :admin )
+ @admin_user .admin = (admin && admin .to_i > 0 )
+
+ respond_to do | format |
+ if @admin_user .save
+ format .html { redirect_to [:admin , @admin_user ], notice : 'User was successfully created.' }
+ format .json { render json : @admin_user , status : :created , location : @admin_user }
+ else
+ format .html { render action : "new" }
+ format .json { render json : @admin_user .errors , status : :unprocessable_entity }
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @admin_user = User .find (params [:id ])
+ @admin_user .destroy
+
+ respond_to do | format |
+ format .html { redirect_to admin_users_url }
+ format .json { head :ok }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ @admin_user = User .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @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 ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @admin_user = User .new ({ projects_limit : Gitlab .config .default_projects_limit }, as : :admin )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @admin_user = User .find (params [:id ])
+
+ @projects = if @admin_user .projects .empty?
+ Project
+ else
+ Project .without_user (@admin_user )
+ end .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ team_update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def team_update
+ @admin_user = User .find (params [:id ])
+
+ UsersProject .user_bulk_import (
+ @admin_user ,
+ params [:project_ids ],
+ params [:project_access ]
+ )
+
+ redirect_to [:admin , @admin_user ], notice : 'Teams were successfully updated.'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unblock ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unblock
+ @admin_user = User .find (params [:id ])
+
+ if @admin_user .update_attribute (:blocked , false )
+ redirect_to :back , alert : "Successfully unblocked"
+ else
+ redirect_to :back , alert : "Error occured. User was not unblocked"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ admin = params [:user ].delete ("admin" )
+
+ if params [:user ][:password ].blank?
+ params [:user ].delete (:password )
+ params [:user ].delete (:password_confirmation )
+ end
+
+ @admin_user = User .find (params [:id ])
+ @admin_user .admin = (admin && admin .to_i > 0 )
+
+ respond_to do | format |
+ if @admin_user .update_attributes (params [:user ], as : :admin )
+ format .html { redirect_to [:admin , @admin_user ], notice : 'User was successfully updated.' }
+ format .json { head :ok }
+ else
+ format .html { render action : "edit" }
+ format .json { render json : @admin_user .errors , status : :unprocessable_entity }
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/AdminController.html b/doc/app/AdminController.html
new file mode 100644
index 00000000..bdda7958
--- /dev/null
+++ b/doc/app/AdminController.html
@@ -0,0 +1,490 @@
+
+
+
+
+
+
+class AdminController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class AdminController
+
+
+
+
Provides a base class for Admin controllers to
+subclass
+
+
Automatically sets the layout and ensures an administrator is logged in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authenticate_admin! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authenticate_admin!
+ return render_404 unless current_user .is_admin?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ApplicationController.html b/doc/app/ApplicationController.html
new file mode 100644
index 00000000..dafa3413
--- /dev/null
+++ b/doc/app/ApplicationController.html
@@ -0,0 +1,1015 @@
+
+
+
+
+
+
+class ApplicationController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ApplicationController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ abilities ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def abilities
+ @abilities ||= Six .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ access_denied! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def access_denied!
+ render "errors/access_denied" , layout : "errors" , status : 404
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_project_abilities ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def add_project_abilities
+ abilities << Ability
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_sign_in_path_for (resource)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_sign_in_path_for resource
+ if resource .is_a? (User ) && resource .respond_to? (:blocked ) && resource .blocked
+ sign_out resource
+ flash [:alert ] = "Your account was blocked"
+ new_user_session_path
+ else
+ super
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_code_access! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_code_access!
+ return access_denied! unless can? (current_user , :download_code , project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_project! (action)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_project! (action )
+ return access_denied! unless can? (current_user , action , project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can? (object, action, subject)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can? (object , action , subject )
+ abilities .allowed? (object , action , subject )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ git_not_found! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def git_not_found!
+ render "errors/git_not_found" , layout : "errors" , status : 404
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ method_missing (method_sym, *arguments, &block)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def method_missing (method_sym , *arguments , &block )
+ if method_sym .to_s =~ %r^authorize_(.*)!$/
+ authorize_project! ($1 .to_sym )
+ else
+ super
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ not_found! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def not_found!
+ render "errors/not_found" , layout : "errors" , status : 404
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project
+ @project ||= current_user .projects .find_by_code (params [:project_id ] || params [:id ])
+ @project || render_404
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reject_blocked! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reject_blocked!
+ if current_user && current_user .blocked
+ sign_out current_user
+ flash [:alert ] = "Your account was blocked"
+ redirect_to new_user_session_path
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ render_404 ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def render_404
+ render file : Rails .root .join ("public" , "404" ), layout : false , status : "404"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ require_non_empty_project ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def require_non_empty_project
+ redirect_to @project if @project .empty_repo?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ set_current_user_for_observers ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def set_current_user_for_observers
+ MergeRequestObserver .current_user = current_user
+ IssueObserver .current_user = current_user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ApplicationDecorator.html b/doc/app/ApplicationDecorator.html
new file mode 100644
index 00000000..72a459bb
--- /dev/null
+++ b/doc/app/ApplicationDecorator.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class ApplicationDecorator - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ApplicationDecorator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ApplicationHelper.html b/doc/app/ApplicationHelper.html
new file mode 100644
index 00000000..9bc4243e
--- /dev/null
+++ b/doc/app/ApplicationHelper.html
@@ -0,0 +1,1018 @@
+
+
+
+
+
+
+module ApplicationHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module ApplicationHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app_theme ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def app_theme
+ Gitlab :: Theme .css_class_by_id (current_user .try (:theme_id ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ current_action? (*args)
+ click to toggle source
+
+
+
+
+
+
Check if a partcular action is the current one
+
+
args - One or more action names to check
+
+
Examples
+
+
+current_action? (:new )
+current_action? (:create )
+current_action? (:new , :create )
+
+
+
+
+
+
+def current_action? (*args )
+ args .any? { | v | v .to_s .downcase == action_name }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ current_controller? (*args)
+ click to toggle source
+
+
+
+
+
+
Check if a particular controller is the current one
+
+
args - One or more controller names to check
+
+
Examples
+
+
+current_controller? (:tree )
+current_controller? (:commits )
+current_controller? (:commits , :tree )
+
+
+
+
+
+
+def current_controller? (*args )
+ args .any? { | v | v .to_s .downcase == controller .controller_name }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ emoji_autocomplete_source ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def emoji_autocomplete_source
+
+
+ Emoji .names .to_s
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gravatar_icon (user_email = '', size = 40)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def gravatar_icon (user_email = '' , size = 40 )
+ if Gitlab .config .disable_gravatar? || user_email .blank?
+ 'no_avatar.png'
+ else
+ gravatar_prefix = request .ssl? ? "https://secure" : "http://www"
+ user_email .strip!
+ "#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=identicon"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ grouped_options_refs (destination = :tree)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def grouped_options_refs (destination = :tree )
+ options = [
+ ["Branch" , @project .branch_names ],
+ [ "Tag" , @project .tag_names ]
+ ]
+
+
+
+ if (@ref && ! options .flatten .include? (@ref ) &&
+ @ref =~ %r^[0-9a-zA-Z]{6,52}$/ )
+ options << ["Commit" , [@ref ]]
+ end
+
+ grouped_options_for_select (options , @ref || @project .default_branch )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ hexdigest (string)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def hexdigest (string )
+ Digest :: SHA1 .hexdigest string
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_commit (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_commit (project )
+ if project .repo_exists?
+ time_ago_in_words (project .commit .committed_date ) + " ago"
+ else
+ "Never"
+ end
+rescue
+ "Never"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ldap_enable? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ldap_enable?
+ Devise .omniauth_providers .include? (:ldap )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_last_activity (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_last_activity project
+ activity = project .last_activity
+ if activity && activity .created_at
+ time_ago_in_words (activity .created_at ) + " ago"
+ else
+ "Never"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ request_protocol ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def request_protocol
+ request .ssl? ? "https" : "http"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search_autocomplete_source ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search_autocomplete_source
+ projects = current_user .projects .map { | p | { label : p .name , url : project_path (p ) } }
+
+ default_nav = [
+ { label : "My Profile" , url : profile_path },
+ { label : "My SSH Keys" , url : keys_path },
+ { label : "My Dashboard" , url : root_path },
+ { label : "Admin Section" , url : admin_root_path },
+ ]
+
+ help_nav = [
+ { label : "Workflow Help" , url : help_workflow_path },
+ { label : "Permissions Help" , url : help_permissions_path },
+ { label : "Web Hooks Help" , url : help_web_hooks_path },
+ { label : "System Hooks Help" , url : help_system_hooks_path },
+ { label : "API Help" , url : help_api_path },
+ { label : "Markdown Help" , url : help_markdown_path },
+ { label : "SSH Keys Help" , url : help_ssh_path },
+ ]
+
+ project_nav = []
+ if @project && ! @project .new_record?
+ project_nav = [
+ { label : "#{@project.name} Issues" , url : project_issues_path (@project ) },
+ { label : "#{@project.name} Commits" , url : project_commits_path (@project , @ref || @project .root_ref ) },
+ { label : "#{@project.name} Merge Requests" , url : project_merge_requests_path (@project ) },
+ { label : "#{@project.name} Milestones" , url : project_milestones_path (@project ) },
+ { label : "#{@project.name} Snippets" , url : project_snippets_path (@project ) },
+ { label : "#{@project.name} Team" , url : project_team_index_path (@project ) },
+ { label : "#{@project.name} Tree" , url : project_tree_path (@project , @ref || @project .root_ref ) },
+ { label : "#{@project.name} Wall" , url : wall_project_path (@project ) },
+ { label : "#{@project.name} Wiki" , url : project_wikis_path (@project ) },
+ ]
+ end
+
+ [projects , default_nav , project_nav , help_nav ].flatten .to_json
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ web_app_url ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def web_app_url
+ "#{request_protocol}://#{Gitlab.config.web_host}/"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/AttachmentUploader.html b/doc/app/AttachmentUploader.html
new file mode 100644
index 00000000..b6e9d1ba
--- /dev/null
+++ b/doc/app/AttachmentUploader.html
@@ -0,0 +1,486 @@
+
+
+
+
+
+
+class AttachmentUploader - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class AttachmentUploader
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ store_dir ()
+ click to toggle source
+
+
+
+
+
+
Override the directory where uploaded files will be stored. This is a
+sensible default for uploaders that are meant to be mounted:
+
+
+
+
+
+def store_dir
+ "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Authority.html b/doc/app/Authority.html
new file mode 100644
index 00000000..92f46c55
--- /dev/null
+++ b/doc/app/Authority.html
@@ -0,0 +1,782 @@
+
+
+
+
+
+
+module Authority - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Authority
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_access (user, *access)
+ click to toggle source
+
+
+
+
+
+
Compatible with all access rights Should be rewrited for new access rights
+
+
+
+
+
+def add_access (user , *access )
+ access = if access .include? (:admin )
+ { project_access : UsersProject :: MASTER }
+ elsif access .include? (:write )
+ { project_access : UsersProject :: DEVELOPER }
+ else
+ { project_access : UsersProject :: REPORTER }
+ end
+ opts = { user : user }
+ opts .merge! (access )
+ users_projects .create (opts )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ allow_read_for? (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def allow_read_for? (user )
+ ! users_projects .where (user_id : user .id ).empty?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ dev_access_for? (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def dev_access_for? (user )
+ ! users_projects .where (user_id : user .id , project_access : [UsersProject :: DEVELOPER , UsersProject :: MASTER ]).empty?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ guest_access_for? (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def guest_access_for? (user )
+ ! users_projects .where (user_id : user .id ).empty?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ master_access_for? (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def master_access_for? (user )
+ ! users_projects .where (user_id : user .id , project_access : [UsersProject :: MASTER ]).empty?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ report_access_for? (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def report_access_for? (user )
+ ! users_projects .where (user_id : user .id , project_access : [UsersProject :: REPORTER , UsersProject :: DEVELOPER , UsersProject :: MASTER ]).empty?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repository_masters ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repository_masters
+ keys = Key .joins ({user : :users_projects }).
+ where ("users_projects.project_id = ? AND users_projects.project_access = ?" , id , UsersProject :: MASTER )
+ keys .map (&:identifier )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repository_readers ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repository_readers
+ keys = Key .joins ({user : :users_projects }).
+ where ("users_projects.project_id = ? AND users_projects.project_access = ?" , id , UsersProject :: REPORTER )
+ keys .map (&:identifier ) + deploy_keys .map (&:identifier )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repository_writers ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repository_writers
+ keys = Key .joins ({user : :users_projects }).
+ where ("users_projects.project_id = ? AND users_projects.project_access = ?" , id , UsersProject :: DEVELOPER )
+ keys .map (&:identifier )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reset_access (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reset_access (user )
+ users_projects .where (project_id : self .id , user_id : user .id ).destroy if self .id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/BaseContext.html b/doc/app/BaseContext.html
new file mode 100644
index 00000000..b9c46738
--- /dev/null
+++ b/doc/app/BaseContext.html
@@ -0,0 +1,605 @@
+
+
+
+
+
+
+class BaseContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class BaseContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ current_user [RW]
+
+
+
+
+
+
+
+
+
+
+
+ params [RW]
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (project, user, params)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (project , user , params )
+ @project , @current_user , @params = project , user , params .dup
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ abilities ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def abilities
+ @abilities ||= begin
+ abilities = Six .new
+ abilities << Ability
+ abilities
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can? (object, action, subject)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can? (object , action , subject )
+ abilities .allowed? (object , action , subject )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/BlameController.html b/doc/app/BlameController.html
new file mode 100644
index 00000000..4b23b227
--- /dev/null
+++ b/doc/app/BlameController.html
@@ -0,0 +1,500 @@
+
+
+
+
+
+
+class BlameController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class BlameController
+
+
+
+
Controller for viewing a file’s blame
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @repo = @project .repo
+ @blame = Grit :: Blob .blame (@repo , @commit .id , @path )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/BlobController.html b/doc/app/BlobController.html
new file mode 100644
index 00000000..e8f069c2
--- /dev/null
+++ b/doc/app/BlobController.html
@@ -0,0 +1,519 @@
+
+
+
+
+
+
+class BlobController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class BlobController
+
+
+
+
Controller for viewing a file’s blame
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ if @tree .is_blob?
+ if @tree .text?
+ encoding = detect_encoding (@tree .data )
+ mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain"
+ else
+ mime_type = @tree .mime_type
+ end
+
+ send_data (
+ @tree .data ,
+ type : mime_type ,
+ disposition : 'inline' ,
+ filename : @tree .name
+ )
+ else
+ not_found!
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Commit.html b/doc/app/Commit.html
new file mode 100644
index 00000000..05a3f3ce
--- /dev/null
+++ b/doc/app/Commit.html
@@ -0,0 +1,1191 @@
+
+
+
+
+
+
+class Commit - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Commit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit [RW]
+
+
+
+
+
+
+
+
+
+
+
+ head [RW]
+
+
+
+
+
+
+
+
+
+
+
+ refs [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits (repo, ref, path = nil, limit = nil, offset = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits (repo , ref , path = nil , limit = nil , offset = nil )
+ if path
+ repo .log (ref , path , max_count : limit , skip : offset )
+ elsif limit && offset
+ repo .commits (ref , limit , offset )
+ else
+ repo .commits (ref )
+ end .map { | c | Commit .new (c ) }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_between (repo, from, to)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_between (repo , from , to )
+ repo .commits_between (from , to ).map { | c | Commit .new (c ) }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_since (repo, date)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_since (repo , date )
+ commits = repo .heads .map do | h |
+ repo .log (h .name , nil , since : date ).each { | c | Commit .new (c , h ) }
+ end .flatten .uniq { | c | c .id }
+
+ commits .sort! do | x , y |
+ y .committed_date <=> x .committed_date
+ end
+
+ commits
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_with_refs (repo, n = 20)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_with_refs (repo , n = 20 )
+ commits = repo .branches .map { | ref | Commit .new (ref .commit , ref ) }
+
+ commits .sort! do | x , y |
+ y .committed_date <=> x .committed_date
+ end
+
+ commits [0 .. n ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ compare (project, from, to)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def compare (project , from , to )
+ result = {
+ commits : [],
+ diffs : [],
+ commit : nil ,
+ same : false
+ }
+
+ return result unless from && to
+
+ first = project .commit (to .try (:strip ))
+ 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 )
+ end
+
+ result
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_or_first (repo, commit_id = nil, root_ref)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def find_or_first (repo , commit_id = nil , root_ref )
+ commit = if commit_id
+ repo .commit (commit_id )
+ else
+ repo .commits (root_ref ).first
+ end
+
+ Commit .new (commit ) if commit
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fresh_commits (repo, n = 10)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def fresh_commits (repo , n = 10 )
+ commits = repo .heads .map do | h |
+ repo .commits (h .name , n ).map { | c | Commit .new (c , h ) }
+ end .flatten .uniq { | c | c .id }
+
+ commits .sort! do | x , y |
+ y .committed_date <=> x .committed_date
+ end
+
+ commits [0 ... n ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (raw_commit, head = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (raw_commit , head = nil )
+ @commit = raw_commit
+ @head = head
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ author_email ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def author_email
+ author .email
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ author_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def author_name
+ utf8 author .name
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ committer_email ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def committer_email
+ committer .email
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ committer_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def committer_name
+ utf8 committer .name
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ created_at ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def created_at
+ committed_date
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ different_committer? ()
+ click to toggle source
+
+
+
+
+
+
Was this commit committed by a different person than the original author?
+
+
+
+
+
+def different_committer?
+ author_name != committer_name || author_email != committer_email
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ parents_count ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def parents_count
+ parents && parents .count || 0
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ prev_commit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def prev_commit
+ parents .try :first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ prev_commit_id ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def prev_commit_id
+ prev_commit .try :id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ safe_message ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def safe_message
+ @safe_message ||= utf8 message
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ short_id (length = 10)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def short_id (length = 10 )
+ id .to_s [0 .. length ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CommitController.html b/doc/app/CommitController.html
new file mode 100644
index 00000000..564161e9
--- /dev/null
+++ b/doc/app/CommitController.html
@@ -0,0 +1,509 @@
+
+
+
+
+
+
+class CommitController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class CommitController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ result = CommitLoadContext .new (project , current_user , params ).execute
+
+ @commit = result [:commit ]
+ git_not_found! unless @commit
+
+ @suppress_diff = result [:suppress_diff ]
+ @note = result [:note ]
+ @line_notes = result [:line_notes ]
+ @notes_count = result [:notes_count ]
+ @comments_allowed = true
+
+ respond_to do | format |
+ format .html do
+ if result [:status ] == :huge_commit
+ render "huge_commit" and return
+ end
+ end
+
+ format .patch
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CommitDecorator.html b/doc/app/CommitDecorator.html
new file mode 100644
index 00000000..3cca57a4
--- /dev/null
+++ b/doc/app/CommitDecorator.html
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+class CommitDecorator - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class CommitDecorator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ author_link (options)
+ click to toggle source
+
+
+
+
+
+
Returns a link to the commit author. If the author has a matching user and
+is a member of the current @project it will link to the team member page.
+Otherwise it will link to the author email as specified in the commit.
+
+
options:
+
+
avatar: true will prepend avatar image
+
+
+
+
+
+def author_link (options )
+ text = if options [:avatar ]
+ avatar = h .image_tag h .gravatar_icon (author_email ), class : "avatar" , width : 16
+ "#{avatar} #{author_name}"
+ else
+ author_name
+ end
+ team_member = @project .try (:team_member_by_name_or_email , author_name , author_email )
+
+ if team_member .nil?
+ h .mail_to author_email , text .html_safe , class : "commit-author-link"
+ else
+ h .link_to text , h .project_team_member_path (@project , team_member ), class : "commit-author-link"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ description ()
+ click to toggle source
+
+
+
+
+
+
Returns the commits description
+
+
cut off, ellipses (`&hellp;`) are prepended to the commit message.
+
+
+
+
+
+def description
+ description = safe_message
+
+ title_end = description .index (%r\n/ )
+ if (! title_end && description .length > 80 ) || (title_end && title_end > 80 )
+ "…" .html_safe << description [70 .. -1 ]
+ else
+ description .split (%r\n/ , 2 )[1 ].try (:chomp )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_title ()
+ click to toggle source
+
+
+
+
+
+
Returns a string describing the commit for use in a link title
+
+
Example
+
+
"Commit: Alex Denisov - Project git clone panel"
+
+
+
+
+
+def link_title
+ "Commit: #{author_name} - #{title}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ title ()
+ click to toggle source
+
+
+
+
+
+
Returns the commits title.
+
+
Usually, the commit title is the first line of the commit message. In case
+this first line is longer than 80 characters, it is cut off after 70
+characters and ellipses (`&hellp;`) are appended.
+
+
+
+
+
+def title
+ title = safe_message
+
+ return no_commit_message if title .blank?
+
+ title_end = title .index (%r\n/ )
+ if (! title_end && title .length > 80 ) || (title_end && title_end > 80 )
+ title [0 .. 69 ] << "…" .html_safe
+ else
+ title .split (%r\n/ , 2 ).first
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ no_commit_message ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def no_commit_message
+ "--no commit message"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CommitLoadContext.html b/doc/app/CommitLoadContext.html
new file mode 100644
index 00000000..feb6dbf4
--- /dev/null
+++ b/doc/app/CommitLoadContext.html
@@ -0,0 +1,513 @@
+
+
+
+
+
+
+class CommitLoadContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class CommitLoadContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ result = {
+ commit : nil ,
+ suppress_diff : false ,
+ line_notes : [],
+ notes_count : 0 ,
+ note : nil ,
+ status : :ok
+ }
+
+ commit = project .commit (params [:id ])
+
+ if commit
+ commit = CommitDecorator .decorate (commit )
+ line_notes = project .commit_line_notes (commit )
+
+ result [:commit ] = commit
+ result [:note ] = project .build_commit_note (commit )
+ result [:line_notes ] = line_notes
+ result [:notes_count ] = line_notes .count + project .commit_notes (commit ).count
+
+ begin
+ result [:suppress_diff ] = true if commit .diffs .size > 200 && ! params [:force_show_diff ]
+ rescue Grit :: Git :: GitTimeout
+ result [:suppress_diff ] = true
+ result [:status ] = :huge_commit
+ end
+ end
+
+ result
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CommitsController.html b/doc/app/CommitsController.html
new file mode 100644
index 00000000..52eaad04
--- /dev/null
+++ b/doc/app/CommitsController.html
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+class CommitsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class CommitsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @repo = @project .repo
+ @limit , @offset = (params [:limit ] || 40 ), (params [:offset ] || 0 )
+
+ @commits = @project .commits (@ref , @path , @limit , @offset )
+ @commits = CommitDecorator .decorate (@commits )
+
+ respond_to do | format |
+ format .html
+ format .js
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CommitsHelper.html b/doc/app/CommitsHelper.html
new file mode 100644
index 00000000..58844bec
--- /dev/null
+++ b/doc/app/CommitsHelper.html
@@ -0,0 +1,625 @@
+
+
+
+
+
+
+module CommitsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module CommitsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build_line_anchor (index, line_new, line_old)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def build_line_anchor (index , line_new , line_old )
+ "#{index}_#{line_old}_#{line_new}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ each_diff_line (diff_arr, index) { |full_line, type, nil, nil, nil| ... }
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def each_diff_line (diff_arr , index )
+ line_old = 1
+ line_new = 1
+ type = nil
+
+ lines_arr = :: Gitlab :: InlineDiff .processing diff_arr
+ lines_arr .each do | line |
+ next if line .match (%r^\-\-\- \/dev\/null/ )
+ next if line .match (%r^\+\+\+ \/dev\/null/ )
+ next if line .match (%r^\-\-\- a/ )
+ next if line .match (%r^\+\+\+ b/ )
+
+ full_line = html_escape (line .gsub (%r\n/ , '' ))
+ full_line = :: Gitlab :: InlineDiff .replace_markers full_line
+
+ if line .match (%r^@@ -/ )
+ type = "match"
+
+ line_old = line .match (%r\-[0-9]*/ )[0 ].to_i .abs rescue 0
+ line_new = line .match (%r\+[0-9]*/ )[0 ].to_i .abs rescue 0
+
+ next if line_old == 1 && line_new == 1
+ yield (full_line , type , nil , nil , nil )
+ next
+ else
+ type = identification_type (line )
+ line_code = build_line_anchor (index , line_new , line_old )
+ yield (full_line , type , line_code , line_new , line_old )
+ end
+
+
+ if line [0 ] == "+"
+ line_new += 1
+ elsif line [0 ] == "-"
+ line_old += 1
+ else
+ line_new += 1
+ line_old += 1
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ identification_type (line)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def identification_type (line )
+ if line [0 ] == "+"
+ "new"
+ elsif line [0 ] == "-"
+ "old"
+ else
+ nil
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image_diff_class (diff)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def image_diff_class (diff )
+ if diff .deleted_file
+ "diff_image_removed"
+ elsif diff .new_file
+ "diff_image_added"
+ else
+ nil
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/CompareController.html b/doc/app/CompareController.html
new file mode 100644
index 00000000..177e22d2
--- /dev/null
+++ b/doc/app/CompareController.html
@@ -0,0 +1,556 @@
+
+
+
+
+
+
+class CompareController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class CompareController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ redirect_to project_compare_path (@project , params [:from ], params [:to ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ result = Commit .compare (project , params [:from ], params [:to ])
+
+ @commits = result [:commits ]
+ @commit = result [:commit ]
+ @diffs = result [:diffs ]
+ @refs_are_same = result [:same ]
+ @line_notes = []
+
+ @commits = CommitDecorator .decorate (@commits )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/DashboardController.html b/doc/app/DashboardController.html
new file mode 100644
index 00000000..e3f4d1b4
--- /dev/null
+++ b/doc/app/DashboardController.html
@@ -0,0 +1,569 @@
+
+
+
+
+
+
+class DashboardController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class DashboardController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @groups = Group .where (id : current_user .projects .pluck (:group_id ))
+ @projects = current_user .projects_with_events
+ @projects = @projects .page (params [:page ]).per (30 )
+
+ @events = Event .in_projects (current_user .project_ids ).limit (20 ).offset (params [:offset ] || 0 )
+ @last_push = current_user .recent_push
+
+ respond_to do | format |
+ format .html
+ format .js
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues ()
+ click to toggle source
+
+
+
+
+
+
Get only assigned issues
+
+
+
+
+
+def issues
+ @projects = current_user .projects .all
+ @user = current_user
+ @issues = current_user .assigned_issues .opened .recent .page (params [:page ]).per (20 )
+ @issues = @issues .includes (:author , :project )
+
+ respond_to do | format |
+ format .html
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_requests ()
+ click to toggle source
+
+
+
+
+
+
Get authored or assigned open merge requests
+
+
+
+
+
+def merge_requests
+ @projects = current_user .projects .all
+ @merge_requests = current_user .cared_merge_requests .recent .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/DeployKeysController.html b/doc/app/DeployKeysController.html
new file mode 100644
index 00000000..318a1441
--- /dev/null
+++ b/doc/app/DeployKeysController.html
@@ -0,0 +1,626 @@
+
+
+
+
+
+
+class DeployKeysController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class DeployKeysController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @key = @project .deploy_keys .new (params [:key ])
+ if @key .save
+ redirect_to project_deploy_keys_path (@project )
+ else
+ render "new"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @key = @project .deploy_keys .find (params [:id ])
+ @key .destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_deploy_keys_url }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @keys = @project .deploy_keys .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @key = @project .deploy_keys .new
+
+ respond_with (@key )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @key = @project .deploy_keys .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ErrorsController.html b/doc/app/ErrorsController.html
new file mode 100644
index 00000000..e77a67d7
--- /dev/null
+++ b/doc/app/ErrorsController.html
@@ -0,0 +1,485 @@
+
+
+
+
+
+
+class ErrorsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ErrorsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ githost ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def githost
+ render "errors/gitolite"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Event.html b/doc/app/Event.html
new file mode 100644
index 00000000..1347cda3
--- /dev/null
+++ b/doc/app/Event.html
@@ -0,0 +1,1222 @@
+
+
+
+
+
+
+class Event - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Event
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Closed
+
+
+
+
+
+
+
+ Created
+
+
+
+
+ Joined
+
+
+
+
+ Left
+
+
+
+
+ Merged
+
+
+
+
+ Pushed
+
+
+
+
+ Reopened
+
+
+
+
+ Updated
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ determine_action (record)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def determine_action (record )
+ if [Issue , MergeRequest ].include? record .class
+ Event :: Created
+ elsif record .kind_of? Note
+ Event :: Commented
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ action_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def action_name
+ if closed?
+ "closed"
+ elsif merged?
+ "merged"
+ elsif joined?
+ 'joined'
+ elsif left?
+ 'left'
+ else
+ "opened"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ allowed? ()
+ click to toggle source
+
+
+
+
+
+
Next events currently enabled for system
+
+
- push
+- new issue
+- merge request
+
+
+
+
+
+def allowed?
+ push? || issue? || merge_request? || membership_changed?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ author ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def author
+ @author ||= User .find (author_id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ changed_issue? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def changed_issue?
+ target_type == "Issue" &&
+ [Closed , Reopened ].include? (action )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ changed_merge_request? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def changed_merge_request?
+ target_type == "MergeRequest" &&
+ [Closed , Reopened ].include? (action )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ closed? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def closed?
+ action == self .class :: Closed
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issue ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issue
+ target if target_type == "Issue"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issue? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issue?
+ target_type == "Issue"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ joined? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def joined?
+ action == Joined
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ left? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def left?
+ action == Left
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ membership_changed? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def membership_changed?
+ joined? || left?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_request ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merge_request
+ target if target_type == "MergeRequest"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_request? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merge_request?
+ target_type == "MergeRequest"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merged? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merged?
+ action == self .class :: Merged
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_issue? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_issue?
+ target_type == "Issue" &&
+ action == Created
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_merge_request? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_merge_request?
+ target_type == "MergeRequest" &&
+ action == Created
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_name
+ if project
+ project .name
+ else
+ "(deleted project)"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ push? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def push?
+ action == self .class :: Pushed && valid_push?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reopened? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reopened?
+ action == self .class :: Reopened
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ target_title ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def target_title
+ target .try :title
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/EventDecorator.html b/doc/app/EventDecorator.html
new file mode 100644
index 00000000..dddb98a6
--- /dev/null
+++ b/doc/app/EventDecorator.html
@@ -0,0 +1,578 @@
+
+
+
+
+
+
+class EventDecorator - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class EventDecorator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ feed_summary ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def feed_summary
+ if self .issue?
+ h .render "events/event_issue" , issue : self .issue
+ elsif self .push?
+ h .render "events/event_push" , event : self
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ feed_title ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def feed_title
+ if self .issue?
+ "#{self.author_name} #{self.action_name} issue ##{self.target_id}: #{self.issue_title} at #{self.project.name}"
+ elsif self .merge_request?
+ "#{self.author_name} #{self.action_name} MR ##{self.target_id}: #{self.merge_request_title} at #{self.project.name}"
+ elsif self .push?
+ "#{self.author_name} #{self.push_action_name} #{self.ref_type} #{self.ref_name} at #{self.project.name}"
+ elsif self .membership_changed?
+ "#{self.author_name} #{self.action_name} #{self.project.name}"
+ else
+ ""
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ feed_url ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def feed_url
+ if self .issue?
+ h .project_issue_url (self .project , self .issue )
+ elsif self .merge_request?
+ h .project_merge_request_url (self .project , self .merge_request )
+
+ elsif self .push?
+ if self .push_with_commits?
+ if self .commits_count > 1
+ h .project_compare_url (self .project , :from => self .parent_commit .id , :to => self .last_commit .id )
+ else
+ h .project_commit_url (self .project , :id => self .last_commit .id )
+ end
+ else
+ h .project_commits_url (self .project , self .ref_name )
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/EventsHelper.html b/doc/app/EventsHelper.html
new file mode 100644
index 00000000..4f7c0454
--- /dev/null
+++ b/doc/app/EventsHelper.html
@@ -0,0 +1,566 @@
+
+
+
+
+
+
+module EventsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module EventsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ event_action_name (event)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def event_action_name (event )
+ target = if event .target_type
+ event .target_type .titleize .downcase
+ else
+ 'project'
+ end
+
+ [event .action_name , target ].join (" " )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ event_image (event)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def event_image event
+ event_image_path = if event .push?
+ "event_push.png"
+ elsif event .merged?
+ "event_mr_merged.png"
+ end
+
+ return nil unless event_image_path
+
+ content_tag :div , class : 'event_icon' do
+ image_tag event_image_path
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_author (event)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def link_to_author (event )
+ project = event .project
+ tm = project .team_member_by_id (event .author_id ) if project
+
+ if tm
+ link_to event .author_name , project_team_member_path (project , tm )
+ else
+ event .author_name
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ExtractsPath.html b/doc/app/ExtractsPath.html
new file mode 100644
index 00000000..e3825307
--- /dev/null
+++ b/doc/app/ExtractsPath.html
@@ -0,0 +1,614 @@
+
+
+
+
+
+
+module ExtractsPath - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module ExtractsPath
+
+
+
+
Module providing methods for dealing with separating a tree-ish string and
+a file path string when combined in a request parameter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ assign_ref_vars ()
+ click to toggle source
+
+
+
+
+
+
Assigns common instance variables for views working with Git tree-ish
+objects
+
+
Assignments are:
+
+@id - A string representing the joined ref and path
+
+@ref - A string representing the ref (e.g., the branch, tag, or commit
+SHA)
+
+@path - A string representing the filesystem path
+
+@commit - A CommitDecorator representing
+the commit from the given ref
+
+@tree - A TreeDecorator representing the
+tree at the given ref/path
+
+
+
If the :id parameter appears to be requesting a specific response format,
+that will be handled as well.
+
+
Automatically renders `not_found!` if a valid tree path could not be
+resolved (e.g., when a user inserts an invalid path or ref).
+
+
+
+
+
+def assign_ref_vars
+
+ if params [:id ].ends_with? ('.atom' )
+ params [:id ].gsub! (%r\.atom$/ , '' )
+ request .format = :atom
+ end
+
+ @ref , @path = extract_ref (params [:id ])
+
+ @id = File .join (@ref , @path )
+
+ @commit = CommitDecorator .decorate (@project .commit (@ref ))
+
+ @tree = Tree .new (@commit .tree , @project , @ref , @path )
+ @tree = TreeDecorator .new (@tree )
+
+ raise InvalidPathError if @tree .invalid?
+rescue NoMethodError , InvalidPathError
+ not_found!
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ExtractsPath/InvalidPathError.html b/doc/app/ExtractsPath/InvalidPathError.html
new file mode 100644
index 00000000..3c8c60fc
--- /dev/null
+++ b/doc/app/ExtractsPath/InvalidPathError.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class ExtractsPath::InvalidPathError - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ExtractsPath::InvalidPathError
+
+
+
+
Raised when given an invalid file path
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/FileSizeValidator.html b/doc/app/FileSizeValidator.html
new file mode 100644
index 00000000..5acdf291
--- /dev/null
+++ b/doc/app/FileSizeValidator.html
@@ -0,0 +1,652 @@
+
+
+
+
+
+
+class FileSizeValidator - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class FileSizeValidator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CHECKS
+
+
+
+
+ DEFAULT_TOKENIZER
+
+
+
+
+ MESSAGES
+
+
+
+
+ RESERVED_OPTIONS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (options)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (options )
+ if range = (options .delete (:in ) || options .delete (:within ))
+ raise ArgumentError , ":in and :within must be a Range" unless range .is_a? (Range )
+ options [:minimum ], options [:maximum ] = range .begin , range .end
+ options [:maximum ] -= 1 if range .exclude_end?
+ end
+
+ super
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ check_validity! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def check_validity!
+ keys = CHECKS .keys & options .keys
+
+ if keys .empty?
+ raise ArgumentError , 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.'
+ end
+
+ keys .each do | key |
+ value = options [key ]
+
+ unless value .is_a? (Integer ) && value >= 0
+ raise ArgumentError , ":#{key} must be a nonnegative Integer"
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ help ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def help
+ Helper .instance
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validate_each (record, attribute, value)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def validate_each (record , attribute , value )
+ raise (ArgumentError , "A CarrierWave::Uploader::Base object was expected" ) unless value .kind_of? CarrierWave :: Uploader :: Base
+
+ value = (options [:tokenizer ] || DEFAULT_TOKENIZER ).call (value ) if value .kind_of? (String )
+
+ CHECKS .each do | key , validity_check |
+ next unless check_value = options [key ]
+
+ value ||= [] if key == :maximum
+
+ value_size = value .size
+ next if value_size .send (validity_check , check_value )
+
+ errors_options = options .except (*RESERVED_OPTIONS )
+ errors_options [:file_size ] = help .number_to_human_size check_value
+
+ default_message = options [MESSAGES [key ]]
+ errors_options [:message ] ||= default_message if default_message
+
+ record .errors .add (attribute , MESSAGES [key ], errors_options )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/FileSizeValidator/Helper.html b/doc/app/FileSizeValidator/Helper.html
new file mode 100644
index 00000000..4fd146c2
--- /dev/null
+++ b/doc/app/FileSizeValidator/Helper.html
@@ -0,0 +1,455 @@
+
+
+
+
+
+
+class FileSizeValidator::Helper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class FileSizeValidator::Helper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/GitHost.html b/doc/app/GitHost.html
new file mode 100644
index 00000000..3197a73f
--- /dev/null
+++ b/doc/app/GitHost.html
@@ -0,0 +1,479 @@
+
+
+
+
+
+
+module GitHost - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module GitHost
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ git_host ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def git_host
+ Gitlab :: Gitolite .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab.html b/doc/app/Gitlab.html
new file mode 100644
index 00000000..0e28a24b
--- /dev/null
+++ b/doc/app/Gitlab.html
@@ -0,0 +1,454 @@
+
+
+
+
+
+
+module Gitlab - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Gitlab
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/API.html b/doc/app/Gitlab/API.html
new file mode 100644
index 00000000..8fad1eec
--- /dev/null
+++ b/doc/app/Gitlab/API.html
@@ -0,0 +1,452 @@
+
+
+
+
+
+
+class Gitlab::API - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::API
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VERSION
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/APIHelpers.html b/doc/app/Gitlab/APIHelpers.html
new file mode 100644
index 00000000..47bf3fb1
--- /dev/null
+++ b/doc/app/Gitlab/APIHelpers.html
@@ -0,0 +1,846 @@
+
+
+
+
+
+
+module Gitlab::APIHelpers - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Gitlab::APIHelpers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ attributes_for_keys (keys)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def attributes_for_keys (keys )
+ attrs = {}
+ keys .each do | key |
+ attrs [key ] = params [key ] if params [key ].present?
+ end
+ attrs
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authenticate! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authenticate!
+ unauthorized! unless current_user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authenticated_as_admin! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authenticated_as_admin!
+ forbidden! unless current_user .is_admin?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize! (action, subject)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize! action , subject
+ unless abilities .allowed? (current_user , action , subject )
+ forbidden!
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ current_user ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def current_user
+ @current_user ||= User .find_by_authentication_token (params [:private_token ] || env ["HTTP_PRIVATE_TOKEN" ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ forbidden! ()
+ click to toggle source
+
+
+
+
+
+
error helpers
+
+
+
+
+
+def forbidden!
+ render_api_error! ('403 Forbidden' , 403 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ not_allowed! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def not_allowed!
+ render_api_error! ('Method Not Allowed' , 405 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ not_found! (resource = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def not_found! (resource = nil )
+ message = ["404" ]
+ message << resource if resource
+ message << "Not Found"
+ render_api_error! (message .join (' ' ), 404 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ paginate (object)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def paginate (object )
+ object .page (params [:page ]).per (params [:per_page ].to_i )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ render_api_error! (message, status)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def render_api_error! (message , status )
+ error! ({'message' => message }, status )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unauthorized! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unauthorized!
+ render_api_error! ('401 Unauthorized' , 401 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ user_project ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def user_project
+ if @project ||= current_user .projects .find_by_id (params [:id ]) ||
+ current_user .projects .find_by_code (params [:id ])
+ else
+ not_found!
+ end
+
+ @project
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/AppLogger.html b/doc/app/Gitlab/AppLogger.html
new file mode 100644
index 00000000..e3a352af
--- /dev/null
+++ b/doc/app/Gitlab/AppLogger.html
@@ -0,0 +1,523 @@
+
+
+
+
+
+
+class Gitlab::AppLogger - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::AppLogger
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .file_name
+ 'application.log'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Auth.html b/doc/app/Gitlab/Auth.html
new file mode 100644
index 00000000..ac4fd556
--- /dev/null
+++ b/doc/app/Gitlab/Auth.html
@@ -0,0 +1,630 @@
+
+
+
+
+
+
+class Gitlab::Auth - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create_from_omniauth (auth, ldap = false)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create_from_omniauth (auth , ldap = false )
+ provider = auth .provider
+ uid = auth .info .uid || auth .uid
+ name = auth .info .name .force_encoding ("utf-8" )
+ email = auth .info .email .downcase unless auth .info .email .nil?
+
+ ldap_prefix = ldap ? '(LDAP) ' : ''
+ raise OmniAuth :: Error , "#{ldap_prefix}#{provider} does not provide an email" " address" if auth .info .email .blank?
+
+ log .info "#{ldap_prefix}Creating user from #{provider} login" " {uid => #{uid}, name => #{name}, email => #{email}}"
+ password = Devise .friendly_token [0 , 8 ].downcase
+ @user = User .new ({
+ extern_uid : uid ,
+ provider : provider ,
+ name : name ,
+ email : email ,
+ password : password ,
+ password_confirmation : password ,
+ projects_limit : Gitlab .config .default_projects_limit ,
+ }, as : :admin )
+ if Gitlab .config .omniauth ['block_auto_created_users' ] && ! ldap
+ @user .blocked = true
+ end
+ @user .save!
+ @user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_for_ldap_auth (auth, signed_in_resource = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def find_for_ldap_auth (auth , signed_in_resource = nil )
+ uid = auth .info .uid
+ provider = auth .provider
+ email = auth .info .email .downcase unless auth .info .email .nil?
+ raise OmniAuth :: Error , "LDAP accounts must provide an uid and email address" if uid .nil? or email .nil?
+
+ if @user = User .find_by_extern_uid_and_provider (uid , provider )
+ @user
+ elsif @user = User .find_by_email (email )
+ log .info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
+ @user .update_attributes (:extern_uid => uid , :provider => provider )
+ @user
+ else
+ create_from_omniauth (auth , true )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_or_new_for_omniauth (auth)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def find_or_new_for_omniauth (auth )
+ provider , uid = auth .provider , auth .uid
+ email = auth .info .email .downcase unless auth .info .email .nil?
+
+ if @user = User .find_by_provider_and_extern_uid (provider , uid )
+ @user
+ elsif @user = User .find_by_email (email )
+ @user .update_attributes (:extern_uid => uid , :provider => provider )
+ @user
+ else
+ if Gitlab .config .omniauth ['allow_single_sign_on' ]
+ @user = create_from_omniauth (auth )
+ @user
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ log ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def log
+ Gitlab :: AppLogger
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Encode.html b/doc/app/Gitlab/Encode.html
new file mode 100644
index 00000000..387e0db2
--- /dev/null
+++ b/doc/app/Gitlab/Encode.html
@@ -0,0 +1,537 @@
+
+
+
+
+
+
+module Gitlab::Encode - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Gitlab::Encode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ detect_encoding (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def detect_encoding message
+ return nil unless message
+
+ hash = CharlockHolmes :: EncodingDetector .detect (message ) rescue {}
+ return hash [:encoding ] ? hash [:encoding ] : nil
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ utf8 (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def utf8 message
+
+ return nil unless message
+
+ message .force_encoding ("utf-8" )
+
+ detect = CharlockHolmes :: EncodingDetector .detect (message )
+ return message if detect [:type ] == :binary
+
+
+ return message if message .valid_encoding?
+
+
+ if detect [:encoding ]
+ message .force_encoding (detect [:encoding ])
+ message .encode! ("utf-8" , detect [:encoding ], undef : :replace , replace : "" , invalid : :replace )
+ end
+
+
+ message .valid_encoding? ? message : raise
+
+
+rescue
+ encoding = detect ? detect [:encoding ] : "unknown"
+ "--broken encoding: #{encoding}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities.html b/doc/app/Gitlab/Entities.html
new file mode 100644
index 00000000..8cd0d837
--- /dev/null
+++ b/doc/app/Gitlab/Entities.html
@@ -0,0 +1,433 @@
+
+
+
+
+
+
+module Gitlab::Entities - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Gitlab::Entities
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/Hook.html b/doc/app/Gitlab/Entities/Hook.html
new file mode 100644
index 00000000..c9eba832
--- /dev/null
+++ b/doc/app/Gitlab/Entities/Hook.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::Hook - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::Hook
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/Issue.html b/doc/app/Gitlab/Entities/Issue.html
new file mode 100644
index 00000000..f713b7ab
--- /dev/null
+++ b/doc/app/Gitlab/Entities/Issue.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::Issue - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::Issue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/Milestone.html b/doc/app/Gitlab/Entities/Milestone.html
new file mode 100644
index 00000000..f762ad29
--- /dev/null
+++ b/doc/app/Gitlab/Entities/Milestone.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::Milestone - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::Milestone
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/Project.html b/doc/app/Gitlab/Entities/Project.html
new file mode 100644
index 00000000..725e6b75
--- /dev/null
+++ b/doc/app/Gitlab/Entities/Project.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::Project - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::Project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/ProjectMember.html b/doc/app/Gitlab/Entities/ProjectMember.html
new file mode 100644
index 00000000..468d3dc1
--- /dev/null
+++ b/doc/app/Gitlab/Entities/ProjectMember.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::ProjectMember - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::ProjectMember
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/ProjectSnippet.html b/doc/app/Gitlab/Entities/ProjectSnippet.html
new file mode 100644
index 00000000..e19fad75
--- /dev/null
+++ b/doc/app/Gitlab/Entities/ProjectSnippet.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::ProjectSnippet - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::ProjectSnippet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/RepoCommit.html b/doc/app/Gitlab/Entities/RepoCommit.html
new file mode 100644
index 00000000..04c118a3
--- /dev/null
+++ b/doc/app/Gitlab/Entities/RepoCommit.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::RepoCommit - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::RepoCommit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/RepoObject.html b/doc/app/Gitlab/Entities/RepoObject.html
new file mode 100644
index 00000000..27f928c1
--- /dev/null
+++ b/doc/app/Gitlab/Entities/RepoObject.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::RepoObject - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::RepoObject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/SSHKey.html b/doc/app/Gitlab/Entities/SSHKey.html
new file mode 100644
index 00000000..43ed0f01
--- /dev/null
+++ b/doc/app/Gitlab/Entities/SSHKey.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::SSHKey - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::SSHKey
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/User.html b/doc/app/Gitlab/Entities/User.html
new file mode 100644
index 00000000..fb978194
--- /dev/null
+++ b/doc/app/Gitlab/Entities/User.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::User - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::User
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/UserBasic.html b/doc/app/Gitlab/Entities/UserBasic.html
new file mode 100644
index 00000000..dcb1e782
--- /dev/null
+++ b/doc/app/Gitlab/Entities/UserBasic.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::UserBasic - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::UserBasic
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Entities/UserLogin.html b/doc/app/Gitlab/Entities/UserLogin.html
new file mode 100644
index 00000000..fde77335
--- /dev/null
+++ b/doc/app/Gitlab/Entities/UserLogin.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Entities::UserLogin - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Entities::UserLogin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/FileEditor.html b/doc/app/Gitlab/FileEditor.html
new file mode 100644
index 00000000..0916d63c
--- /dev/null
+++ b/doc/app/Gitlab/FileEditor.html
@@ -0,0 +1,647 @@
+
+
+
+
+
+
+class Gitlab::FileEditor - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::FileEditor
+
+
+
+
GitLab file editor
+
+
It gives you ability to make changes to files & commit this changes
+from GitLab UI.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+ ref [RW]
+
+
+
+
+
+
+
+
+
+
+
+ user [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (user, project, ref)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (user , project , ref )
+ self .user = user
+ self .project = project
+ self .ref = ref
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update (path, content, commit_message, last_commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update (path , content , commit_message , last_commit )
+ return false unless can_edit? (path , last_commit )
+
+ Grit :: Git .with_timeout (10 .seconds ) do
+ lock_file = Rails .root .join ("tmp" , "#{project.path}.lock" )
+
+ File .open (lock_file , "w+" ) do | f |
+ f .flock (File :: LOCK_EX )
+
+ unless project .satellite .exists?
+ raise "Satellite doesn't exist"
+ end
+
+ project .satellite .clear
+
+ Dir .chdir (project .satellite .path ) do
+ r = Grit :: Repo .new ('.' )
+ r .git .sh "git reset --hard"
+ r .git .sh "git fetch origin"
+ r .git .sh "git config user.name \"#{user.name}\""
+ r .git .sh "git config user.email \"#{user.email}\""
+ r .git .sh "git checkout -b #{ref} origin/#{ref}"
+ File .open (path , 'w' ){| f | f .write (content )}
+ r .git .sh "git add ."
+ r .git .sh "git commit -am '#{commit_message}'"
+ output = r .git .sh "git push origin #{ref}"
+
+ if output =~ %rreject/
+ return false
+ end
+ end
+ end
+ end
+ true
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can_edit? (path, last_commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can_edit? (path , last_commit )
+ current_last_commit = @project .last_commit_for (ref , path ).sha
+ last_commit == current_last_commit
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/GitLogger.html b/doc/app/Gitlab/GitLogger.html
new file mode 100644
index 00000000..c37bce98
--- /dev/null
+++ b/doc/app/Gitlab/GitLogger.html
@@ -0,0 +1,523 @@
+
+
+
+
+
+
+class Gitlab::GitLogger - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::GitLogger
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .file_name
+ 'githost.log'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Gitolite.html b/doc/app/Gitlab/Gitolite.html
new file mode 100644
index 00000000..60ef3b13
--- /dev/null
+++ b/doc/app/Gitlab/Gitolite.html
@@ -0,0 +1,716 @@
+
+
+
+
+
+
+class Gitlab::Gitolite - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Gitolite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ config ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def config
+ Gitlab :: GitoliteConfig .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create_repository (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ enable_automerge ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def enable_automerge
+ config .admin_all_repo!
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ remove_key (key_id, projects)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def remove_key key_id , projects
+ config .apply do | config |
+ config .rm_key (key_id )
+ config .update_projects (projects )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ remove_repository (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def remove_repository project
+ config .destroy_project! (project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ set_key (key_id, key_content, projects)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def set_key key_id , key_content , projects
+ config .apply do | config |
+ config .write_key (key_id , key_content )
+ config .update_projects (projects )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_repository (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_repository project
+ config .update_project! (project .path , project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ url_to_repo (path)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def url_to_repo path
+ Gitlab .config .ssh_path + "#{path}.git"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Gitolite/AccessDenied.html b/doc/app/Gitlab/Gitolite/AccessDenied.html
new file mode 100644
index 00000000..64a3b17a
--- /dev/null
+++ b/doc/app/Gitlab/Gitolite/AccessDenied.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::Gitolite::AccessDenied - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Gitolite::AccessDenied
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/GitoliteConfig.html b/doc/app/Gitlab/GitoliteConfig.html
new file mode 100644
index 00000000..19671089
--- /dev/null
+++ b/doc/app/Gitlab/GitoliteConfig.html
@@ -0,0 +1,994 @@
+
+
+
+
+
+
+class Gitlab::GitoliteConfig - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::GitoliteConfig
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ conf [R]
+
+
+
+
+
+
+
+
+
+
+
+ config_tmp_dir [R]
+
+
+
+
+
+
+
+
+
+
+
+ ga_repo [R]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ admin_all_repo ()
+ click to toggle source
+
+
+
+
+
+
Enable access to all repos for gitolite admin. We use it for accept merge
+request feature
+
+
+
+
+
+def admin_all_repo
+ owner_name = Gitlab .config .gitolite_admin_key
+
+
+ repo_name = "@all"
+ repo = if conf .has_repo? (repo_name )
+ conf .get_repo (repo_name )
+ else
+ :: Gitolite :: Config :: Repo .new (repo_name )
+ end
+
+ repo .add_permission ("RW+" , "" , owner_name )
+ conf .add_repo (repo , true )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ admin_all_repo! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def admin_all_repo!
+ apply { | config | config .admin_all_repo }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ apply () { |self| ... }
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def apply
+ Timeout :: timeout (30 ) do
+ File .open (Rails .root .join ('tmp' , "gitlabhq-gitolite.lock" ), "w+" ) do | f |
+ begin
+
+
+ f .flock (File :: LOCK_EX )
+
+
+
+ pull (config_tmp_dir )
+
+
+
+ @conf = ga_repo .config
+
+
+
+
+ yield (self )
+
+
+
+
+ ga_repo .save
+
+
+
+ push (config_tmp_dir )
+ ensure
+
+
+
+ FileUtils .rm_rf (File .join (config_tmp_dir , 'gitolite' ))
+
+
+ FileUtils .rm_rf (config_tmp_dir )
+
+
+
+ f .flock (File :: LOCK_UN )
+ end
+ end
+ end
+rescue PullError => ex
+ log ("Pull error -> " + ex .message )
+ raise Gitolite :: AccessDenied , ex .message
+
+rescue PushError => ex
+ log ("Push error -> " + " " + ex .message )
+ raise Gitolite :: AccessDenied , ex .message
+
+rescue Exception => ex
+ log (ex .class .name + " " + ex .message )
+ raise Gitolite :: AccessDenied .new ("gitolite timeout" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy_project (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy_project (project )
+ FileUtils .rm_rf (project .path_to_repo )
+ conf .rm_repo (project .path )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy_project! (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy_project! (project )
+ apply do | config |
+ config .destroy_project (project )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ log (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def log message
+ Gitlab :: GitLogger .error (message )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rm_key (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def rm_key (user )
+ key_path = File .join (config_tmp_dir , 'gitolite/keydir' , "#{user}.pub" )
+ ga_key = :: Gitolite :: SSHKey .from_file (key_path )
+ ga_repo .rm_key (ga_key )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_project (repo_name, project)
+ click to toggle source
+
+
+
+
+
+
update or create
+
+
+
+
+
+def update_project (repo_name , project )
+ repo = update_project_config (project , conf )
+ conf .add_repo (repo , true )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_project! (repo_name, project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_project! (repo_name , project )
+ apply do | config |
+ config .update_project (repo_name , project )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_project_config (project, conf)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_project_config (project , conf )
+ repo_name = project .path
+
+ repo = if conf .has_repo? (repo_name )
+ conf .get_repo (repo_name )
+ else
+ :: Gitolite :: Config :: Repo .new (repo_name )
+ end
+
+ name_readers = project .repository_readers
+ name_writers = project .repository_writers
+ name_masters = project .repository_masters
+
+ pr_br = project .protected_branches .map (&:name ).join ("$ " )
+
+ repo .clean_permissions
+
+
+ unless name_writers .blank? || pr_br .blank?
+ repo .add_permission ("-" , pr_br .strip + "$ " , name_writers )
+ end
+
+
+ repo .add_permission ("R" , "" , name_readers ) unless name_readers .blank?
+
+
+ repo .add_permission ("RW+" , "" , name_writers ) unless name_writers .blank?
+ repo .add_permission ("RW+" , "" , name_masters ) unless name_masters .blank?
+
+
+ repo .set_git_config ("core.sharedRepository" , "0660" )
+
+ repo
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_projects (projects)
+ click to toggle source
+
+
+
+
+
+
Updates many projects and uses project.path as the repo path An order of
+magnitude faster than #update_project
+
+
+
+
+
+def update_projects (projects )
+ projects .each do | project |
+ repo = update_project_config (project , conf )
+ conf .add_repo (repo , true )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ write_key (id, key)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def write_key (id , key )
+ File .open (File .join (config_tmp_dir , 'gitolite/keydir' ,"#{id}.pub" ), 'w' ) do | f |
+ f .write (key .gsub (%r\n/ ,'' ))
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/GitoliteConfig/PullError.html b/doc/app/Gitlab/GitoliteConfig/PullError.html
new file mode 100644
index 00000000..8e5a1510
--- /dev/null
+++ b/doc/app/Gitlab/GitoliteConfig/PullError.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::GitoliteConfig::PullError - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::GitoliteConfig::PullError
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/GitoliteConfig/PushError.html b/doc/app/Gitlab/GitoliteConfig/PushError.html
new file mode 100644
index 00000000..c1541f49
--- /dev/null
+++ b/doc/app/Gitlab/GitoliteConfig/PushError.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class Gitlab::GitoliteConfig::PushError - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::GitoliteConfig::PushError
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/GraphCommit.html b/doc/app/Gitlab/GraphCommit.html
new file mode 100644
index 00000000..b8ffa6f4
--- /dev/null
+++ b/doc/app/Gitlab/GraphCommit.html
@@ -0,0 +1,967 @@
+
+
+
+
+
+
+class Gitlab::GraphCommit - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::GraphCommit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ refs [RW]
+
+
+
+
+
+
+
+
+
+
+
+ space [RW]
+
+
+
+
+
+
+
+
+
+
+
+ time [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_free_space (time_range)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .find_free_space (time_range )
+ reserved = []
+ for day in time_range
+ reserved += @_reserved [day ]
+ end
+ space = 1
+ while reserved .include? space do
+ space += 1
+ end
+ space
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index_commits (commits)
+ click to toggle source
+
+
+
+
+
+
Method is adding time and space on the list of commits. As well as returns
+date list corelated with time set on commits.
+
+
@param [Array<GraphCommit>] comits to index
+
+
@return [Array<TimeDate>] list of commit dates corelated with time on
+commits
+
+
+
+
+
+def self .index_commits (commits )
+ days , heads = [], []
+ map = {}
+
+ commits .reverse .each_with_index do | c ,i |
+ c .time = i
+ days [i ] = c .committed_date
+ map [c .id ] = c
+ heads += c .refs unless c .refs .nil?
+ end
+
+ heads .select! {| h | h .is_a? Grit :: Head or h .is_a? Grit :: Remote }
+
+ heads .sort! do | a ,b |
+ if a .name == "master"
+ -1
+ elsif b .name == "master"
+ 1
+ else
+ b .commit .committed_date <=> a .commit .committed_date
+ end
+ end
+
+ @_reserved = {}
+ days .each_index do | i |
+ @_reserved [i ] = []
+ end
+
+ heads .each do | h |
+ if map .include? h .commit .id then
+ place_chain (map [h .commit .id ], map )
+ end
+ end
+ days
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mark_reserved (time_range, space)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .mark_reserved (time_range , space )
+ for day in time_range
+ @_reserved [day ].push (space )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (commit )
+ @_commit = commit
+ @time = -1
+ @space = 0
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ place_chain (commit, map, parent_time = nil)
+ click to toggle source
+
+
+
+
+
+
Add space mark on commit and its parents
+
+
@param [GraphCommit] the commit object. @param
+[Hash<String,GraphCommit>] map of commits
+
+
+
+
+
+def self .place_chain (commit , map , parent_time = nil )
+ leaves = take_left_leaves (commit , map )
+ if leaves .empty? then
+ return
+ end
+ space = find_free_space (leaves .last .time .. leaves .first .time )
+ leaves .each {| l | l .space = space }
+
+ min_time = leaves .last .time
+ parents = leaves .last .parents .collect
+ parents .each do | p |
+ if map .include? p .id then
+ parent = map [p .id ]
+ if parent .time < min_time then
+ min_time = parent .time
+ end
+ end
+ end
+ if parent_time .nil? then
+ max_time = leaves .first .time
+ else
+ max_time = parent_time - 1
+ end
+ mark_reserved (min_time .. max_time , space )
+
+ leaves .each do | l |
+ parents = l .parents .collect
+ .select {| p | map .include? p .id and map [p .id ].space == 0 }
+ for p in parents
+ place_chain (map [p .id ], map , l .time )
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ take_left_leaves (commit, map)
+ click to toggle source
+
+
+
+
+
+
Takes most left subtree branch of commits which don’t have space mark yet.
+
+
@param [GraphCommit] the commit object. @param
+[Hash<String,GraphCommit>] map of commits
+
+
@return [Array<GraphCommit>] list of branch commits
+
+
+
+
+
+def self .take_left_leaves (commit , map )
+ leaves = []
+ leaves .push (commit ) if commit .space == 0
+ while true
+ parent = commit .parents .collect
+ .select {| p | map .include? p .id and map [p .id ].space == 0 }
+ if parent .count == 0 then
+ return leaves
+ else
+ commit = map [parent .first .id ]
+ leaves .push (commit )
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_graph (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .to_graph (project )
+ @repo = project .repo
+ commits = Grit :: Commit .find_all (@repo , nil , {max_count : 650 })
+
+ ref_cache = {}
+
+ commits .map! {| c | GraphCommit .new (Commit .new (c ))}
+ commits .each { | commit | commit .add_refs (ref_cache , @repo ) }
+
+ days = GraphCommit .index_commits (commits )
+ @days_json = days .compact .collect {| d | [d .day , d .strftime ("%b" )] }.to_json
+ @commits_json = commits .map (&:to_graph_hash ).to_json
+
+ return @days_json , @commits_json
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_refs (ref_cache, repo)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def add_refs (ref_cache , repo )
+ if ref_cache .empty?
+ repo .refs .each do | ref |
+ ref_cache [ref .commit .id ] ||= []
+ ref_cache [ref .commit .id ] << ref
+ end
+ end
+ @refs = ref_cache [@_commit .id ] if ref_cache .include? (@_commit .id )
+ @refs ||= []
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ method_missing (m, *args, &block)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def method_missing (m , *args , &block )
+ @_commit .send (m , *args , &block )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_graph_hash ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_graph_hash
+ h = {}
+ h [:parents ] = self .parents .collect do | p |
+ [p .id ,0 ,0 ]
+ end
+ h [:author ] = Gitlab :: Encode .utf8 (author .name )
+ h [:time ] = time
+ h [:space ] = space
+ h [:refs ] = refs .collect {| r | r .name }.join (" " ) unless refs .nil?
+ h [:id ] = sha
+ h [:date ] = date
+ h [:message ] = escape_once (Gitlab :: Encode .utf8 (message ))
+ h [:login ] = author .email
+ h
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/InlineDiff.html b/doc/app/Gitlab/InlineDiff.html
new file mode 100644
index 00000000..91eeae9c
--- /dev/null
+++ b/doc/app/Gitlab/InlineDiff.html
@@ -0,0 +1,611 @@
+
+
+
+
+
+
+class Gitlab::InlineDiff - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::InlineDiff
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FINISH
+
+
+
+
+ START
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _indexes_of_changed_lines (diff_arr)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def _indexes_of_changed_lines diff_arr
+ chain_of_first_symbols = ""
+ diff_arr .each_with_index do | line , i |
+ chain_of_first_symbols += line [0 ]
+ end
+ chain_of_first_symbols .gsub! (%r[^\-\+]/ , "#" )
+
+ offset = 0
+ indexes = []
+ while index = chain_of_first_symbols .index ("#-+#" , offset )
+ indexes << index
+ offset = index + 1
+ end
+ indexes
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ processing (diff_arr)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def processing diff_arr
+ indexes = _indexes_of_changed_lines diff_arr
+
+ indexes .each do | index |
+ first_line = diff_arr [index + 1 ]
+ second_line = diff_arr [index + 2 ]
+ max_length = [first_line .size , second_line .size ].max
+
+ first_the_same_symbols = 0
+ (0 .. max_length + 1 ).each do | i |
+ first_the_same_symbols = i - 1
+ if first_line [i ] != second_line [i ] && i > 0
+ break
+ end
+ end
+ first_token = first_line [0 .. first_the_same_symbols ][1 .. -1 ]
+ diff_arr [index + 1 ].sub! (first_token , first_token + START )
+ diff_arr [index + 2 ].sub! (first_token , first_token + START )
+ last_the_same_symbols = 0
+ (1 .. max_length + 1 ).each do | i |
+ last_the_same_symbols = - i
+ shortest_line = second_line .size > first_line .size ? first_line : second_line
+ if ( first_line [- i ] != second_line [- i ] ) || "#{first_token}#{START}" .size == shortest_line [1 .. - i ].size
+ break
+ end
+ end
+ last_the_same_symbols += 1
+ last_token = first_line [last_the_same_symbols .. -1 ]
+ diff_arr [index + 1 ].sub! (%r#{Regexp.escape(last_token)}$/ , FINISH + last_token )
+ diff_arr [index + 2 ].sub! (%r#{Regexp.escape(last_token)}$/ , FINISH + last_token )
+ end
+ diff_arr
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ replace_markers (line)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def replace_markers line
+ line .gsub! (START , "<span class='idiff'>" )
+ line .gsub! (FINISH , "</span>" )
+ line
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Issues.html b/doc/app/Gitlab/Issues.html
new file mode 100644
index 00000000..eda99ed1
--- /dev/null
+++ b/doc/app/Gitlab/Issues.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class Gitlab::Issues - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Issues
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Logger.html b/doc/app/Gitlab/Logger.html
new file mode 100644
index 00000000..8cc6cdea
--- /dev/null
+++ b/doc/app/Gitlab/Logger.html
@@ -0,0 +1,583 @@
+
+
+
+
+
+
+class Gitlab::Logger - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Logger
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .build
+ new (Rails .root .join ("log" , file_name ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .error (message )
+ build .error (message )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ info (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .info (message )
+ build .info (message )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ read_latest ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .read_latest
+ path = Rails .root .join ("log" , file_name )
+ self .build unless File .exist? (path )
+ logs = File .read (path ).split ("\n" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Markdown.html b/doc/app/Gitlab/Markdown.html
new file mode 100644
index 00000000..12691455
--- /dev/null
+++ b/doc/app/Gitlab/Markdown.html
@@ -0,0 +1,580 @@
+
+
+
+
+
+
+module Gitlab::Markdown - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Gitlab::Markdown
+
+
+
+
Custom parser for GitLab-flavored Markdown
+
+
It replaces references in the text with links to the appropriate items in
+GitLab.
+
+
Supported reference formats are:
+
+
* @foo for team members
+* #123 for issues
+* !123 for merge requests
+* $123 for snippets
+* 123456 for commits
+
+
It also parses Emoji codes to insert images. See www.emoji-cheat-sheet.com/ for
+a list of the supported icons.
+
+
Examples
+
+
>> gfm ("Hey @david, can you fix this?" )
+=> "Hey <a href=" / gitlab / team_members / 1 ">@david</a>, can you fix this?"
+
+>> gfm ("Commit 35d5f7c closes #1234" )
+=> "Commit <a href=" / gitlab / commits / 35 d5f7c ">35d5f7c</a> closes <a href=" / gitlab / issues / 1234 ">#1234</a>"
+
+>> gfm (":trollface:" )
+=> "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title =\":trollface:\" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EMOJI_PATTERN
+
+
+
+
+ REFERENCE_PATTERN
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ html_options [R]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gfm (text, html_options = {})
+ click to toggle source
+
+
+
+
+
+
Public: Parse the provided text with GitLab-Flavored Markdown
+
+
text - the source text #html_options - extra
+options for the reference links as given to link_to
+
+
Note: reference links will only be generated if @project is set
+
+
+
+
+
+def gfm (text , html_options = {})
+ return text if text .nil?
+
+
+
+
+ text = text .dup .to_str
+
+ @html_options = html_options
+
+
+
+ extractions = {}
+ text .gsub! (%r{<pre>.*?</pre>|<code>.*?</code>} ) do | match |
+ md5 = Digest :: MD5 .hexdigest (match )
+ extractions [md5 ] = match
+ "{gfm-extraction-#{md5}}"
+ end
+
+
+
+ text = parse (text )
+
+
+ text .gsub! (%r\{gfm-extraction-(\h{32})\}/ ) do
+ extractions [$1 ]
+ end
+
+ sanitize text .html_safe , attributes : ActionView :: Base .sanitized_allowed_attributes + %w(id class)
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Merge.html b/doc/app/Gitlab/Merge.html
new file mode 100644
index 00000000..99a66cd5
--- /dev/null
+++ b/doc/app/Gitlab/Merge.html
@@ -0,0 +1,628 @@
+
+
+
+
+
+
+class Gitlab::Merge - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Merge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_request [RW]
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+ user [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (merge_request, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (merge_request , user )
+ @merge_request = merge_request
+ @project = merge_request .project
+ @user = user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can_be_merged? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can_be_merged?
+ in_locked_and_timed_satellite do | merge_repo |
+ merge_in_satellite! (merge_repo )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge! ()
+ click to toggle source
+
+
+
+
+
+
Merges the source branch into the target branch in the satellite and pushes
+it back to Gitolite . It also removes the source
+branch if requested in the merge request.
+
+
Returns false if the merge produced conflicts Returns false if pushing from
+the satallite to Gitolite failed or was
+rejected Returns true otherwise
+
+
+
+
+
+def merge!
+ in_locked_and_timed_satellite do | merge_repo |
+ if merge_in_satellite! (merge_repo )
+
+
+ merge_repo .git .push ({raise : true }, :origin , merge_request .target_branch )
+
+
+ if merge_request .should_remove_source_branch && ! project .root_ref? (merge_request .source_branch )
+
+ merge_repo .git .push ({raise : true }, :origin , ":#{merge_request.source_branch}" )
+ end
+
+
+ true
+ end
+ end
+rescue Grit :: Git :: CommandFailed
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Milestones.html b/doc/app/Gitlab/Milestones.html
new file mode 100644
index 00000000..aac605b2
--- /dev/null
+++ b/doc/app/Gitlab/Milestones.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class Gitlab::Milestones - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Milestones
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Projects.html b/doc/app/Gitlab/Projects.html
new file mode 100644
index 00000000..a44cba3c
--- /dev/null
+++ b/doc/app/Gitlab/Projects.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class Gitlab::Projects - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Projects
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Satellite.html b/doc/app/Gitlab/Satellite.html
new file mode 100644
index 00000000..4615d1c6
--- /dev/null
+++ b/doc/app/Gitlab/Satellite.html
@@ -0,0 +1,664 @@
+
+
+
+
+
+
+class Gitlab::Satellite - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Satellite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PARKING_BRANCH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize project
+ self .project = project
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ clear ()
+ click to toggle source
+
+
+
+
+
+
will be deleted all branches except PARKING_BRANCH
+
+
+
+
+
+def clear
+ Dir .chdir (path ) do
+ heads = Grit :: Repo .new ("." ).heads .map {| head | head .name }
+ if heads .include? PARKING_BRANCH
+ %xgit checkout #{PARKING_BRANCH}`
+ else
+ %xgit checkout -b #{PARKING_BRANCH}`
+ end
+ heads .delete (PARKING_BRANCH )
+ heads .each do | head |
+ %xgit branch -D #{head}`
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ %xgit clone #{project.url_to_repo} #{path}`
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ exists? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def exists?
+ File .exists? path
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ path ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def path
+ Rails .root .join ("tmp" , "repo_satellites" , project .path )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Session.html b/doc/app/Gitlab/Session.html
new file mode 100644
index 00000000..12f3433e
--- /dev/null
+++ b/doc/app/Gitlab/Session.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class Gitlab::Session - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Session
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Theme.html b/doc/app/Gitlab/Theme.html
new file mode 100644
index 00000000..00b3e5f6
--- /dev/null
+++ b/doc/app/Gitlab/Theme.html
@@ -0,0 +1,493 @@
+
+
+
+
+
+
+class Gitlab::Theme - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Theme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ css_class_by_id (id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .css_class_by_id (id )
+ themes = {
+ 1 => "ui_basic" ,
+ 2 => "ui_mars" ,
+ 3 => "ui_modern"
+ }
+
+ id ||= 1
+
+ return themes [id ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Gitlab/Users.html b/doc/app/Gitlab/Users.html
new file mode 100644
index 00000000..c9712874
--- /dev/null
+++ b/doc/app/Gitlab/Users.html
@@ -0,0 +1,441 @@
+
+
+
+
+
+
+class Gitlab::Users - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Gitlab::Users
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/GitlabMarkdownHelper.html b/doc/app/GitlabMarkdownHelper.html
new file mode 100644
index 00000000..6bf172ac
--- /dev/null
+++ b/doc/app/GitlabMarkdownHelper.html
@@ -0,0 +1,559 @@
+
+
+
+
+
+
+module GitlabMarkdownHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module GitlabMarkdownHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_gfm (body, url, html_options = {})
+ click to toggle source
+
+
+
+
+
+
Use this in places where you would normally use link_to(gfm(…), …).
+
+
It solves a problem occurring with nested links (i.e. “<a>outer text
+<a>gfm ref</a> more outer text</a>”). This will not be
+interpreted as intended. Browsers will parse something like “<a>outer
+text </a><a>gfm ref</a> more outer text” (notice the last
+part is not linked any more). #link_to_gfm
+corrects that. It wraps all parts to explicitly produce the correct linking
+behavior (i.e. “<a>outer text </a><a>gfm
+ref</a><a> more outer text</a>”).
+
+
+
+
+
+def link_to_gfm (body , url , html_options = {})
+ return "" if body .blank?
+
+ gfm_body = gfm (escape_once (body ), html_options )
+
+ gfm_body .gsub! (%r{<a.*?>.*?</a>} ) do | match |
+ "</a>#{match}#{link_to("", url, html_options)[0..-5]}"
+ end
+
+ link_to (gfm_body .html_safe , url , html_options )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ markdown (text)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def markdown (text )
+ unless @markdown
+ gitlab_renderer = Redcarpet :: Render :: GitlabHTML .new (self ,
+
+ filter_html : true ,
+ with_toc_data : true ,
+ hard_wrap : true )
+ @markdown = Redcarpet :: Markdown .new (gitlab_renderer ,
+
+ no_intra_emphasis : true ,
+ tables : true ,
+ fenced_code_blocks : true ,
+ autolink : true ,
+ strikethrough : true ,
+ lax_html_blocks : true ,
+ space_after_headers : true ,
+ superscript : true )
+ end
+
+ @markdown .render (text ).html_safe
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Grack.html b/doc/app/Grack.html
new file mode 100644
index 00000000..e3c5bbd4
--- /dev/null
+++ b/doc/app/Grack.html
@@ -0,0 +1,433 @@
+
+
+
+
+
+
+module Grack - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Grack
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Grack/Auth.html b/doc/app/Grack/Auth.html
new file mode 100644
index 00000000..5da483f7
--- /dev/null
+++ b/doc/app/Grack/Auth.html
@@ -0,0 +1,734 @@
+
+
+
+
+
+
+class Grack::Auth - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Grack::Auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+ user [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can? (object, action, subject)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can? (object , action , subject )
+ abilities .allowed? (object , action , subject )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ current_ref ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def current_ref
+ if @env ["HTTP_CONTENT_ENCODING" ] =~ %rgzip/
+ input = Zlib :: GzipReader .new (@request .body ).read
+ else
+ input = @request .body .read
+ end
+
+ @request .body .rewind
+ %rrefs\/heads\/([\w-]+)/ .match (input ).to_a .first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ valid? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def valid?
+
+ email , password = @auth .credentials
+ self .user = User .find_by_email (email )
+ return false unless user .try (:valid_password? , password )
+
+
+ ENV ['GL_USER' ] = email
+
+ ENV ['GL_BYPASS_UPDATE_HOOK' ] = "true"
+
+
+ @env ['PATH_INFO' ] = @request .path
+ @env ['SCRIPT_NAME' ] = ""
+
+
+ if m = %r^\/([\w-]+).git/ .match (@request .path_info ).to_a
+ self .project = Project .find_by_path (m .last )
+ return false unless project
+ end
+
+
+ if @request .get?
+ validate_get_request
+ elsif @request .post?
+ validate_post_request
+ else
+ false
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validate_get_request ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def validate_get_request
+ true
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validate_post_request ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def validate_post_request
+ if @request .path_info .end_with? ('git-upload-pack' )
+ can? (user , :push_code , project )
+ elsif @request .path_info .end_with? ('git-receive-pack' )
+ action = if project .protected_branch? (current_ref )
+ :push_code_to_protected_branches
+ else
+ :push_code
+ end
+
+ can? (user , action , project )
+ else
+ false
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ abilities ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def abilities
+ @abilities ||= begin
+ abilities = Six .new
+ abilities << Ability
+ abilities
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Group.html b/doc/app/Group.html
new file mode 100644
index 00000000..a23e1da6
--- /dev/null
+++ b/doc/app/Group.html
@@ -0,0 +1,555 @@
+
+
+
+
+
+
+class Group - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Group
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search (query)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .search query
+ where ("name LIKE :query OR code LIKE :query" , query : "%#{query}%" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_param ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_param
+ code
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ users ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def users
+ User .joins (:users_projects ).where (users_projects : {project_id : project_ids }).uniq
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/GroupsController.html b/doc/app/GroupsController.html
new file mode 100644
index 00000000..72e1022c
--- /dev/null
+++ b/doc/app/GroupsController.html
@@ -0,0 +1,735 @@
+
+
+
+
+
+
+class GroupsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class GroupsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues ()
+ click to toggle source
+
+
+
+
+
+
Get only assigned issues
+
+
+
+
+
+def issues
+ @user = current_user
+ @issues = current_user .assigned_issues .opened
+ @issues = @issues .of_group (@group ).recent .page (params [:page ]).per (20 )
+ @issues = @issues .includes (:author , :project )
+
+ respond_to do | format |
+ format .html
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_requests ()
+ click to toggle source
+
+
+
+
+
+
Get authored or assigned open merge requests
+
+
+
+
+
+def merge_requests
+ @merge_requests = current_user .cared_merge_requests
+ @merge_requests = @merge_requests .of_group (@group ).recent .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ people ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def people
+ @users = group .users .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search
+ result = SearchContext .new (project_ids , params ).execute
+
+ @projects = result [:projects ]
+ @merge_requests = result [:merge_requests ]
+ @issues = result [:issues ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @events = Event .in_projects (project_ids ).limit (20 ).offset (params [:offset ] || 0 )
+ @last_push = current_user .recent_push
+
+ respond_to do | format |
+ format .html
+ format .js
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ group ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def group
+ @group ||= Group .find_by_code (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_ids ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_ids
+ projects .map (&:id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ projects ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def projects
+ @projects ||= current_user .projects_with_events .where (group_id : @group .id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/HelpController.html b/doc/app/HelpController.html
new file mode 100644
index 00000000..afbbeb0b
--- /dev/null
+++ b/doc/app/HelpController.html
@@ -0,0 +1,484 @@
+
+
+
+
+
+
+class HelpController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class HelpController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/HooksController.html b/doc/app/HooksController.html
new file mode 100644
index 00000000..70fd89c3
--- /dev/null
+++ b/doc/app/HooksController.html
@@ -0,0 +1,595 @@
+
+
+
+
+
+
+class HooksController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class HooksController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @hook = @project .hooks .new (params [:hook ])
+ @hook .save
+
+ if @hook .valid?
+ redirect_to project_hooks_path (@project )
+ else
+ @hooks = @project .hooks .all
+ render :index
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @hook = @project .hooks .find (params [:id ])
+ @hook .destroy
+
+ redirect_to project_hooks_path (@project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @hooks = @project .hooks .all
+ @hook = ProjectHook .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def test
+ TestHookContext .new (project , current_user , params ).execute
+
+ redirect_to :back
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Issue.html b/doc/app/Issue.html
new file mode 100644
index 00000000..e8a7881c
--- /dev/null
+++ b/doc/app/Issue.html
@@ -0,0 +1,501 @@
+
+
+
+
+
+
+class Issue - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Issue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ open_for (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .open_for (user )
+ opened .assigned (user )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssueCommonality.html b/doc/app/IssueCommonality.html
new file mode 100644
index 00000000..336580d8
--- /dev/null
+++ b/doc/app/IssueCommonality.html
@@ -0,0 +1,641 @@
+
+
+
+
+
+
+module IssueCommonality - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module IssueCommonality
+
+
+
+
Contains common functionality shared between Issues and MergeRequests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_assigned? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_assigned?
+ ! ! assignee_id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_being_closed? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_being_closed?
+ closed_changed? && closed
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_being_reassigned? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_being_reassigned?
+ assignee_id_changed?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_being_reopened? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_being_reopened?
+ closed_changed? && ! closed
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new?
+ today? && created_at == updated_at
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ today? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def today?
+ Date .today == created_at .to_date
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssueCommonality/ClassMethods.html b/doc/app/IssueCommonality/ClassMethods.html
new file mode 100644
index 00000000..d4ab179d
--- /dev/null
+++ b/doc/app/IssueCommonality/ClassMethods.html
@@ -0,0 +1,479 @@
+
+
+
+
+
+
+module IssueCommonality::ClassMethods - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module IssueCommonality::ClassMethods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search (query)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search (query )
+ where ("title like :query" , query : "%#{query}%" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssueObserver.html b/doc/app/IssueObserver.html
new file mode 100644
index 00000000..7f16a865
--- /dev/null
+++ b/doc/app/IssueObserver.html
@@ -0,0 +1,571 @@
+
+
+
+
+
+
+class IssueObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class IssueObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (issue )
+ if issue .assignee && issue .assignee != current_user
+ Notify .new_issue_email (issue .id ).deliver
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_update (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_update (issue )
+ send_reassigned_email (issue ) if issue .is_being_reassigned?
+
+ status = nil
+ status = 'closed' if issue .is_being_closed?
+ status = 'reopened' if issue .is_being_reopened?
+ 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 )
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ send_reassigned_email (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def send_reassigned_email (issue )
+ recipient_ids = [issue .assignee_id , issue .assignee_id_was ].keep_if {| id | id && id != current_user .id }
+
+ recipient_ids .each do | recipient_id |
+ Notify .reassigned_issue_email (recipient_id , issue .id , issue .assignee_id_was ).deliver
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssuesBulkUpdateContext.html b/doc/app/IssuesBulkUpdateContext.html
new file mode 100644
index 00000000..1d87a757
--- /dev/null
+++ b/doc/app/IssuesBulkUpdateContext.html
@@ -0,0 +1,503 @@
+
+
+
+
+
+
+class IssuesBulkUpdateContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class IssuesBulkUpdateContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ update_data = params [:update ]
+
+ issues_ids = update_data [:issues_ids ].split ("," )
+ milestone_id = update_data [:milestone_id ]
+ assignee_id = update_data [:assignee_id ]
+ status = update_data [:status ]
+
+ opts = {}
+ opts [:milestone_id ] = milestone_id if milestone_id .present?
+ opts [:assignee_id ] = assignee_id if assignee_id .present?
+ opts [:closed ] = (status == "closed" ) if status .present?
+
+ issues = Issue .where (id : issues_ids ).all
+ issues = issues .select { | issue | can? (current_user , :modify_issue , issue ) }
+ issues .each { | issue | issue .update_attributes (opts ) }
+ {
+ count : issues .count ,
+ success : ! issues .count .zero?
+ }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssuesController.html b/doc/app/IssuesController.html
new file mode 100644
index 00000000..6b3edbb6
--- /dev/null
+++ b/doc/app/IssuesController.html
@@ -0,0 +1,996 @@
+
+
+
+
+
+
+class IssuesController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class IssuesController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bulk_update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def bulk_update
+ result = IssuesBulkUpdateContext .new (project , current_user , params ).execute
+ redirect_to :back , notice : "#{result[:count]} issues updated"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @issue = @project .issues .new (params [:issue ])
+ @issue .author = current_user
+ @issue .save
+
+ respond_to do | format |
+ format .html do
+ if @issue .valid?
+ redirect_to project_issue_path (@project , @issue )
+ else
+ render :new
+ end
+ end
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @issue .destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_issues_path }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ respond_with (@issue )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @issues = issues_filtered
+ @issues = @issues .page (params [:page ]).per (20 )
+
+ respond_to do | format |
+ format .html
+ format .js
+ format .atom { render layout : false }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @issue = @project .issues .new (params [:issue ])
+ respond_with (@issue )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search
+ terms = params ['terms' ]
+
+ @issues = issues_filtered
+ @issues = @issues .where ("title LIKE ?" , "%#{terms}%" ) unless terms .blank?
+ @issues = @issues .page (params [:page ]).per (100 )
+
+ render partial : 'issues'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @note = @project .notes .new (noteable : @issue )
+
+ respond_to do | format |
+ format .html
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sort ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def sort
+ return render_404 unless can? (current_user , :admin_issue , @project )
+
+ @issues = @project .issues .where (id : params ['issue' ])
+ @issues .each do | issue |
+ issue .position = params ['issue' ].index (issue .id .to_s ) + 1
+ issue .save
+ end
+
+ render nothing : true
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @issue .update_attributes (params [:issue ].merge (author_id_of_changes : current_user .id ))
+
+ respond_to do | format |
+ format .js
+ format .html do
+ if @issue .valid?
+ redirect_to [@project , @issue ]
+ else
+ render :edit
+ end
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_admin_issue! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_admin_issue!
+ return render_404 unless can? (current_user , :admin_issue , @issue )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_modify_issue! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_modify_issue!
+ return render_404 unless can? (current_user , :modify_issue , @issue )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issue ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issue
+ @issue ||= @project .issues .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues_filtered ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issues_filtered
+ @issues = IssuesListContext .new (project , current_user , params ).execute
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module_enabled ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def module_enabled
+ return render_404 unless @project .issues_enabled
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssuesHelper.html b/doc/app/IssuesHelper.html
new file mode 100644
index 00000000..d58a5f7f
--- /dev/null
+++ b/doc/app/IssuesHelper.html
@@ -0,0 +1,698 @@
+
+
+
+
+
+
+module IssuesHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module IssuesHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issue_css_classes (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issue_css_classes issue
+ classes = "issue"
+ classes << " closed" if issue .closed
+ classes << " today" if issue .today?
+ classes
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues_filter ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issues_filter
+ {
+ all : "all" ,
+ closed : "closed" ,
+ to_me : "assigned-to-me" ,
+ open : "open"
+ }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_issue_assignee (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_issue_author (issue)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_issues_filter_path (project, params = {})
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_issues_filter_path project , params = {}
+ params [:f ] ||= cookies ['issue_filter' ]
+ project_issues_path project , params
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unassigned_filter ()
+ click to toggle source
+
+
+
+
+
+
Returns an OpenStruct object suitable for use by
+options_from_collection_for_select
to allow filtering issues
+by an unassigned User or Milestone
+
+
+
+
+
+def unassigned_filter
+
+ OpenStruct .new (id : 0 , title : 'Unspecified' , name : 'Unassigned' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/IssuesListContext.html b/doc/app/IssuesListContext.html
new file mode 100644
index 00000000..01acec45
--- /dev/null
+++ b/doc/app/IssuesListContext.html
@@ -0,0 +1,537 @@
+
+
+
+
+
+
+class IssuesListContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class IssuesListContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ @issues = case params [:f ]
+ when issues_filter [:all ] then @project .issues
+ when issues_filter [:closed ] then @project .issues .closed
+ when issues_filter [:to_me ] then @project .issues .opened .assigned (current_user )
+ else @project .issues .opened
+ end
+
+ @issues = @issues .tagged_with (params [:label_name ]) if params [:label_name ].present?
+ @issues = @issues .includes (:author , :project ).order ("updated_at" )
+
+
+ if params [:assignee_id ].present?
+ @issues = @issues .where (assignee_id : (params [:assignee_id ] == '0' ? nil : params [:assignee_id ]))
+ end
+
+
+ if params [:milestone_id ].present?
+ @issues = @issues .where (milestone_id : (params [:milestone_id ] == '0' ? nil : params [:milestone_id ]))
+ end
+
+ @issues
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Key.html b/doc/app/Key.html
new file mode 100644
index 00000000..afbcea93
--- /dev/null
+++ b/doc/app/Key.html
@@ -0,0 +1,700 @@
+
+
+
+
+
+
+class Key - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Key
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fingerprintable_key ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def fingerprintable_key
+ return true unless key
+
+ file = Tempfile .new ('key_file' )
+ begin
+ file .puts key
+ file .rewind
+ fingerprint_output = %xssh-keygen -lf #{file.path} 2>&1`
+ ensure
+ file .close
+ file .unlink
+ end
+ errors .add (:key , "can't be fingerprinted" ) if fingerprint_output .match ("failed" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_deploy_key ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_deploy_key
+ true if project_id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_deploy? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_deploy?
+ Key .where (identifier : identifier ).count == 0
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ projects ()
+ click to toggle source
+
+
+
+
+
+
projects that has this key
+
+
+
+
+
+def projects
+ if is_deploy_key
+ [project ]
+ else
+ user .projects
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ set_identifier ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def set_identifier
+ if is_deploy_key
+ self .identifier = "deploy_#{Digest::MD5.hexdigest(key)}"
+ else
+ self .identifier = "#{user.identifier}_#{Time.now.to_i}"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ strip_white_space ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def strip_white_space
+ self .key = self .key .strip unless self .key .blank?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unique_key ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unique_key
+ query = Key .where (key : key )
+ query = query .where ('(project_id IS NULL OR project_id = ?)' , project_id ) if project_id
+ if (query .count > 0 )
+ errors .add :key , 'already exist.'
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/KeyObserver.html b/doc/app/KeyObserver.html
new file mode 100644
index 00000000..bdaf9f84
--- /dev/null
+++ b/doc/app/KeyObserver.html
@@ -0,0 +1,530 @@
+
+
+
+
+
+
+class KeyObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class KeyObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_destroy (key)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_destroy (key )
+ return if key .is_deploy_key && ! key .last_deploy?
+ git_host .remove_key (key .identifier , key .projects )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_save (key)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_save (key )
+ git_host .set_key (key .identifier , key .key , key .projects )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/KeysController.html b/doc/app/KeysController.html
new file mode 100644
index 00000000..13fac402
--- /dev/null
+++ b/doc/app/KeysController.html
@@ -0,0 +1,624 @@
+
+
+
+
+
+
+class KeysController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class KeysController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @key = current_user .keys .new (params [:key ])
+ @key .save
+
+ respond_with (@key )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @key = current_user .keys .find (params [:id ])
+ @key .destroy
+
+ respond_to do | format |
+ format .html { redirect_to keys_url }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @keys = current_user .keys .all
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @key = current_user .keys .new
+
+ respond_with (@key )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @key = current_user .keys .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/LabelsController.html b/doc/app/LabelsController.html
new file mode 100644
index 00000000..7dece840
--- /dev/null
+++ b/doc/app/LabelsController.html
@@ -0,0 +1,523 @@
+
+
+
+
+
+
+class LabelsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class LabelsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @labels = @project .issues_labels .order ('count DESC' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module_enabled ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def module_enabled
+ return render_404 unless @project .issues_enabled
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MergeRequest.html b/doc/app/MergeRequest.html
new file mode 100644
index 00000000..7dbe6f4f
--- /dev/null
+++ b/doc/app/MergeRequest.html
@@ -0,0 +1,1478 @@
+
+
+
+
+
+
+class MergeRequest - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class MergeRequest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BROKEN_DIFF
+
+
+
+
+ CANNOT_BE_MERGED
+
+
+
+
+ CAN_BE_MERGED
+
+
+
+
+ UNCHECKED
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ should_remove_source_branch [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_all_by_branch (branch_name)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .find_all_by_branch (branch_name )
+ where ("source_branch LIKE :branch OR target_branch LIKE :branch" , branch : branch_name )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ automerge! (current_user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def automerge! (current_user )
+ if Gitlab :: Merge .new (self , current_user ).merge! && self .unmerged_commits .empty?
+ self .merge! (current_user .id )
+ true
+ end
+rescue
+ self .mark_as_unmergable
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ broken_diffs? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def broken_diffs?
+ diffs == [BROKEN_DIFF ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ can_be_merged? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def can_be_merged?
+ state == CAN_BE_MERGED
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ check_if_can_be_merged ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def check_if_can_be_merged
+ self .state = if Gitlab :: Merge .new (self , self .author ).can_be_merged?
+ CAN_BE_MERGED
+ else
+ CANNOT_BE_MERGED
+ end
+ self .save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ closed_event ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def closed_event
+ self .project .events .where (target_id : self .id , target_type : "MergeRequest" , action : Event :: Closed ).last
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits
+ st_commits || []
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diffs ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def diffs
+ st_diffs || []
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ human_state ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def human_state
+ states = {
+ CAN_BE_MERGED => "can_be_merged" ,
+ CANNOT_BE_MERGED => "cannot_be_merged" ,
+ UNCHECKED => "unchecked"
+ }
+ states [self .state ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_commit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_commit
+ commits .first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mark_as_merged! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def mark_as_merged!
+ self .merged = true
+ self .closed = true
+ save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mark_as_unchecked ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def mark_as_unchecked
+ self .state = UNCHECKED
+ self .save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mark_as_unmergable ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def mark_as_unmergable
+ self .state = CANNOT_BE_MERGED
+ self .save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge! (user_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merge! (user_id )
+ self .mark_as_merged!
+ Event .create (
+ project : self .project ,
+ action : Event :: Merged ,
+ target_id : self .id ,
+ target_type : "MergeRequest" ,
+ author_id : user_id
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_event ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merge_event
+ self .project .events .where (target_id : self .id , target_type : "MergeRequest" , action : Event :: Merged ).last
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merged? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merged?
+ merged && merge_event
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mr_and_commit_notes ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+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 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ open? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def open?
+ ! closed
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ probably_merged? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def probably_merged?
+ unmerged_commits .empty? &&
+ commits .any? && open?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reload_code ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reload_code
+ self .reloaded_commits
+ self .reloaded_diffs
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reloaded_commits ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reloaded_commits
+ if open? && unmerged_commits .any?
+ self .st_commits = unmerged_commits
+ save
+ end
+ commits
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reloaded_diffs ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reloaded_diffs
+ if open? && unmerged_diffs .any?
+ self .st_diffs = unmerged_diffs
+ self .save
+ end
+
+rescue Grit :: Git :: GitTimeout
+ self .st_diffs = [BROKEN_DIFF ]
+ self .save
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_raw ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_raw
+ FileUtils .mkdir_p (Rails .root .join ("tmp" , "patches" ))
+ patch_path = Rails .root .join ("tmp" , "patches" , "merge_request_#{self.id}.patch" )
+
+ from = commits .last .id
+ to = source_branch
+
+ project .repo .git .run ('' , "format-patch" , " > #{patch_path.to_s}" , {}, ["#{from}..#{to}" , "--stdout" ])
+
+ patch_path
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unchecked? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unchecked?
+ state == UNCHECKED
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unmerged_commits ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unmerged_commits
+ self .project .repo .
+ commits_between (self .target_branch , self .source_branch ).
+ map {| c | Commit .new (c )}.
+ sort_by (&:created_at ).
+ reverse
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unmerged_diffs ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def unmerged_diffs
+
+
+
+ common_commit = project .repo .git .native (:merge_base , {}, [target_branch , source_branch ]).strip
+ diffs = project .repo .diff (common_commit , source_branch )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ valid_diffs? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def valid_diffs?
+ ! broken_diffs?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validate_branches ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def validate_branches
+ if target_branch == source_branch
+ errors .add :base , "You can not use same branch for source and target branches"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MergeRequestObserver.html b/doc/app/MergeRequestObserver.html
new file mode 100644
index 00000000..f2d0dbd7
--- /dev/null
+++ b/doc/app/MergeRequestObserver.html
@@ -0,0 +1,569 @@
+
+
+
+
+
+
+class MergeRequestObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class MergeRequestObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (merge_request)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (merge_request )
+ if merge_request .assignee && merge_request .assignee != current_user
+ Notify .new_merge_request_email (merge_request .id ).deliver
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_update (merge_request)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_update (merge_request )
+ send_reassigned_email (merge_request ) if merge_request .is_being_reassigned?
+
+ status = nil
+ status = 'closed' if merge_request .is_being_closed?
+ status = 'reopened' if merge_request .is_being_reopened?
+ if status
+ Note .create_status_change_note (merge_request , current_user , status )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ send_reassigned_email (merge_request)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def send_reassigned_email (merge_request )
+ recipients_ids = merge_request .assignee_id_was , merge_request .assignee_id
+ recipients_ids .delete current_user .id
+
+ recipients_ids .each do | recipient_id |
+ Notify .reassigned_merge_request_email (recipient_id , merge_request .id , merge_request .assignee_id_was ).deliver
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MergeRequestsController.html b/doc/app/MergeRequestsController.html
new file mode 100644
index 00000000..ef257c6c
--- /dev/null
+++ b/doc/app/MergeRequestsController.html
@@ -0,0 +1,1114 @@
+
+
+
+
+
+
+class MergeRequestsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class MergeRequestsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ automerge ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def automerge
+ return access_denied! unless can? (current_user , :accept_mr , @project )
+ if @merge_request .open? && @merge_request .can_be_merged?
+ @merge_request .should_remove_source_branch = params [:should_remove_source_branch ]
+ @merge_request .automerge! (current_user )
+ @status = true
+ else
+ @status = false
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ automerge_check ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def automerge_check
+ if @merge_request .unchecked?
+ @merge_request .check_if_can_be_merged
+ end
+ render json : {state : @merge_request .human_state }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branch_from ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branch_from
+ @commit = project .commit (params [:ref ])
+ @commit = CommitDecorator .decorate (@commit )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branch_to ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branch_to
+ @commit = project .commit (params [:ref ])
+ @commit = CommitDecorator .decorate (@commit )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @merge_request = @project .merge_requests .new (params [:merge_request ])
+ @merge_request .author = current_user
+
+ if @merge_request .save
+ @merge_request .reload_code
+ redirect_to [@project , @merge_request ], notice : 'Merge request was successfully created.'
+ else
+ render action : "new"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @merge_request .destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_merge_requests_url (@project ) }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diffs ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def diffs
+ @diffs = @merge_request .diffs
+ @commit = @merge_request .last_commit
+
+ @comments_allowed = true
+ @line_notes = @merge_request .notes .where ("line_code is not null" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @merge_requests = MergeRequestsLoadContext .new (project , current_user , params ).execute
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @merge_request = @project .merge_requests .new (params [:merge_request ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ raw ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def raw
+ send_file @merge_request .to_raw
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ respond_to do | format |
+ format .html
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ if @merge_request .update_attributes (params [:merge_request ].merge (author_id_of_changes : current_user .id ))
+ @merge_request .reload_code
+ @merge_request .mark_as_unchecked
+ redirect_to [@project , @merge_request ], notice : 'Merge request was successfully updated.'
+ else
+ render action : "edit"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_admin_merge_request! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_admin_merge_request!
+ return render_404 unless can? (current_user , :admin_merge_request , @merge_request )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_modify_merge_request! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_modify_merge_request!
+ return render_404 unless can? (current_user , :modify_merge_request , @merge_request )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ define_show_vars ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def define_show_vars
+
+ @note = @project .notes .new (noteable : @merge_request )
+
+
+
+ @commits = @merge_request .commits
+ @commits = CommitDecorator .decorate (@commits )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ merge_request ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def merge_request
+ @merge_request ||= @project .merge_requests .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module_enabled ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def module_enabled
+ return render_404 unless @project .merge_requests_enabled
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ validates_merge_request ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def validates_merge_request
+
+ return git_not_found! unless @project .repo .heads .map (&:name ).include? (@merge_request .target_branch )
+
+
+
+ return git_not_found! if ! @project .repo .heads .map (&:name ).include? (@merge_request .source_branch ) && @merge_request .commits .blank?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MergeRequestsHelper.html b/doc/app/MergeRequestsHelper.html
new file mode 100644
index 00000000..fec9b0e0
--- /dev/null
+++ b/doc/app/MergeRequestsHelper.html
@@ -0,0 +1,599 @@
+
+
+
+
+
+
+module MergeRequestsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module MergeRequestsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_merge_request_assignee (merge_request)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_merge_request_author (merge_request)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+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
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mr_css_classes (mr)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def mr_css_classes mr
+ classes = "merge_request"
+ classes << " closed" if mr .closed
+ classes << " merged" if mr .merged?
+ classes
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_mr_path_from_push_event (event)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_mr_path_from_push_event (event )
+ new_project_merge_request_path (
+ event .project ,
+ merge_request : {
+ source_branch : event .branch_name ,
+ target_branch : event .project .root_ref ,
+ title : event .branch_name .titleize
+ }
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MergeRequestsLoadContext.html b/doc/app/MergeRequestsLoadContext.html
new file mode 100644
index 00000000..5c1b8829
--- /dev/null
+++ b/doc/app/MergeRequestsLoadContext.html
@@ -0,0 +1,496 @@
+
+
+
+
+
+
+class MergeRequestsLoadContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class MergeRequestsLoadContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ type = params [:f ]
+
+ merge_requests = project .merge_requests
+
+ merge_requests = case type
+ when 'all' then merge_requests
+ when 'closed' then merge_requests .closed
+ when 'assigned-to-me' then merge_requests .opened .assigned (current_user )
+ else merge_requests .opened
+ end .page (params [:page ]).per (20 )
+
+ merge_requests .includes (:author , :project ).order ("closed, created_at desc" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Milestone.html b/doc/app/Milestone.html
new file mode 100644
index 00000000..cc3bdc58
--- /dev/null
+++ b/doc/app/Milestone.html
@@ -0,0 +1,589 @@
+
+
+
+
+
+
+class Milestone - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Milestone
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ active ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .active
+ where ("due_date > ? OR due_date IS NULL" , Date .today )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ expires_at ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def expires_at
+ "expires at #{due_date.stamp("Aug 21, 2011")}" if due_date
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ participants ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def participants
+ User .where (id : issues .pluck (:assignee_id ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ percent_complete ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def percent_complete
+ ((self .issues .closed .count * 100 ) / self .issues .count ).abs
+rescue ZeroDivisionError
+ 100
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/MilestonesController.html b/doc/app/MilestonesController.html
new file mode 100644
index 00000000..e15d6fef
--- /dev/null
+++ b/doc/app/MilestonesController.html
@@ -0,0 +1,816 @@
+
+
+
+
+
+
+class MilestonesController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class MilestonesController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @milestone = @project .milestones .new (params [:milestone ])
+
+ if @milestone .save
+ redirect_to project_milestone_path (@project , @milestone )
+ else
+ render "new"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ return access_denied! unless can? (current_user , :admin_milestone , @milestone )
+
+ @milestone .destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_milestones_path }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ respond_with (@milestone )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @milestones = case params [:f ]
+ when 'all' ; @project .milestones
+ else @project .milestones .active
+ end
+
+ @milestones = @milestones .includes (:project ).order ("due_date" )
+ @milestones = @milestones .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @milestone = @project .milestones .new
+ respond_with (@milestone )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @issues = @milestone .issues
+ @users = @milestone .participants
+
+ respond_to do | format |
+ format .html
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @milestone .update_attributes (params [:milestone ])
+
+ respond_to do | format |
+ format .js
+ format .html do
+ if @milestone .valid?
+ redirect_to [@project , @milestone ]
+ else
+ render :edit
+ end
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_admin_milestone! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_admin_milestone!
+ return render_404 unless can? (current_user , :admin_milestone , @project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ milestone ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def milestone
+ @milestone ||= @project .milestones .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module_enabled ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def module_enabled
+ return render_404 unless @project .issues_enabled
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Note.html b/doc/app/Note.html
new file mode 100644
index 00000000..24a474b0
--- /dev/null
+++ b/doc/app/Note.html
@@ -0,0 +1,777 @@
+
+
+
+
+
+
+class Note - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Note
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notify [RW]
+
+
+
+
+
+
+
+
+
+
+
+ notify_author [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create_status_change_note (noteable, author, status)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .create_status_change_note (noteable , author , status )
+ create ({
+ noteable : noteable ,
+ project : noteable .project ,
+ author : author ,
+ note : "_Status changed to #{status}_"
+ }, without_protection : true )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit_author ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit_author
+ @commit_author ||=
+ project .users .find_by_email (noteable .author_email ) ||
+ project .users .find_by_name (noteable .author_name )
+rescue
+ nil
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ downvote? ()
+ click to toggle source
+
+
+
+
+
+
Returns true if this is a downvote note, otherwise false is returned
+
+
+
+
+
+def downvote?
+ note .start_with? ('-1' ) || note .start_with? (':-1:' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for_commit? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def for_commit?
+ noteable_type == "Commit"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for_diff_line? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def for_diff_line?
+ line_code .present?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ noteable ()
+ click to toggle source
+
+
+
+
+
+
override to return commits, which are not active record
+
+
+
+
+
+def noteable
+ if for_commit?
+ project .commit (noteable_id )
+ else
+ super
+ end
+
+
+rescue
+ nil
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notify_only_author? (user)
+ click to toggle source
+
+
+
+
+
+
Check if we can notify commit author with email about our comment
+
+
If commit author email exist in project and commit author is not passed
+user we can send email to him
+
+
params:
+
+
user - current user
+
+
return:
+
+
Boolean
+
+
+
+
+
+def notify_only_author? (user )
+ for_commit? && commit_author &&
+ commit_author .email != user .email
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ upvote? ()
+ click to toggle source
+
+
+
+
+
+
Returns true if this is an upvote note, otherwise false is returned
+
+
+
+
+
+def upvote?
+ note .start_with? ('+1' ) || note .start_with? (':+1:' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/NoteObserver.html b/doc/app/NoteObserver.html
new file mode 100644
index 00000000..d0528833
--- /dev/null
+++ b/doc/app/NoteObserver.html
@@ -0,0 +1,603 @@
+
+
+
+
+
+
+class NoteObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class NoteObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (note)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (note )
+ send_notify_mails (note )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notify_team (note)
+ click to toggle source
+
+
+
+
+
+
Notifies the whole team except the author of note
+
+
+
+
+
+def notify_team (note )
+
+ noteable_type = note .noteable_type || "Wall"
+ notify_method = "note_#{noteable_type.underscore}_email" .to_sym
+
+ if Notify .respond_to? notify_method
+ team_without_note_author (note ).map do | u |
+ Notify .send (notify_method , u .id , note .id ).deliver
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ send_notify_mails (note)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def send_notify_mails (note )
+ if note .notify
+ notify_team (note )
+ elsif note .notify_author
+
+ Notify .note_commit_email (note .commit_author .id , note .id ).deliver
+ else
+
+ nil
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ team_without_note_author (note)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def team_without_note_author (note )
+ note .project .users .reject { | u | u .id == note .author .id }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Notes.html b/doc/app/Notes.html
new file mode 100644
index 00000000..d6bcc540
--- /dev/null
+++ b/doc/app/Notes.html
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+module Notes - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Notes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Notes/CreateContext.html b/doc/app/Notes/CreateContext.html
new file mode 100644
index 00000000..6d4c8449
--- /dev/null
+++ b/doc/app/Notes/CreateContext.html
@@ -0,0 +1,490 @@
+
+
+
+
+
+
+class Notes::CreateContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Notes::CreateContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ note = project .notes .new (params [:note ])
+ note .author = current_user
+ note .notify = true if params [:notify ] == '1'
+ note .notify_author = true if params [:notify_author ] == '1'
+ note .save
+ note
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Notes/LoadContext.html b/doc/app/Notes/LoadContext.html
new file mode 100644
index 00000000..273fc0f0
--- /dev/null
+++ b/doc/app/Notes/LoadContext.html
@@ -0,0 +1,513 @@
+
+
+
+
+
+
+class Notes::LoadContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Notes::LoadContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ target_type = params [:target_type ]
+ target_id = params [:target_id ]
+ after_id = params [:after_id ]
+ before_id = params [:before_id ]
+
+
+ @notes = case target_type
+ when "commit"
+ project .commit_notes (project .commit (target_id )).fresh .limit (20 )
+ when "issue"
+ project .issues .find (target_id ).notes .inc_author .fresh .limit (20 )
+ when "merge_request"
+ project .merge_requests .find (target_id ).mr_and_commit_notes .inc_author .fresh .limit (20 )
+ when "snippet"
+ project .snippets .find (target_id ).notes .fresh
+ when "wall"
+
+ project .common_notes .order ("created_at DESC, id DESC" ).limit (50 )
+ when "wiki"
+ project .wiki_notes .limit (20 )
+ end
+
+ @notes = if after_id
+ @notes .where ("id > ?" , after_id )
+ elsif before_id
+ @notes .where ("id < ?" , before_id )
+ else
+ @notes
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/NotesController.html b/doc/app/NotesController.html
new file mode 100644
index 00000000..5623d4a2
--- /dev/null
+++ b/doc/app/NotesController.html
@@ -0,0 +1,636 @@
+
+
+
+
+
+
+class NotesController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class NotesController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @note = Notes :: CreateContext .new (project , current_user , params ).execute
+
+ respond_to do | format |
+ format .html {redirect_to :back }
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @note = @project .notes .find (params [:id ])
+ return access_denied! unless can? (current_user , :admin_note , @note )
+ @note .destroy
+
+ respond_to do | format |
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ notes
+ if params [:target_type ] == "merge_request"
+ @mixed_targets = true
+ @main_target_type = params [:target_type ].camelize
+ end
+
+ respond_with (@notes )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ preview ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def preview
+ render text : view_context .markdown (params [:note ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ notes ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def notes
+ @notes = Notes :: LoadContext .new (project , current_user , params ).execute
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/NotesHelper.html b/doc/app/NotesHelper.html
new file mode 100644
index 00000000..c2940f8d
--- /dev/null
+++ b/doc/app/NotesHelper.html
@@ -0,0 +1,581 @@
+
+
+
+
+
+
+module NotesHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module NotesHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_commit_diff_line_note (note)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def link_to_commit_diff_line_note (note )
+ commit = note .noteable
+ diff_index , diff_old_line , diff_new_line = note .line_code .split ('_' )
+
+ link_file = commit .diffs [diff_index .to_i ].new_path
+ link_line = diff_new_line
+
+ link_to "#{link_file}:L#{link_line}" , project_commit_path (@project , commit , anchor : note .line_code )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading_more_notes? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def loading_more_notes?
+ params [:loading_more ].present?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ loading_new_notes? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def loading_new_notes?
+ params [:loading_new ].present?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_for_main_target? (note)
+ click to toggle source
+
+
+
+
+
+
Helps to distinguish e.g. commit notes in mr notes list
+
+
+
+
+
+def note_for_main_target? (note )
+ ! @mixed_targets || @main_target_type == note .noteable_type
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Notify.html b/doc/app/Notify.html
new file mode 100644
index 00000000..933e1cbc
--- /dev/null
+++ b/doc/app/Notify.html
@@ -0,0 +1,883 @@
+
+
+
+
+
+
+class Notify - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Notify
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issue_status_changed_email (recipient_id, issue_id, status, updated_by_user_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issue_status_changed_email (recipient_id , issue_id , status , updated_by_user_id )
+ @issue = Issue .find issue_id
+ @issue_status = status
+ @updated_by = User .find updated_by_user_id
+ mail (to : recipient (recipient_id ),
+ subject : subject ("changed issue ##{@issue.id}" , @issue .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_issue_email (issue_id)
+ click to toggle source
+
+
+
+
+
+
Issue
+
+
+
+
+
+def new_issue_email (issue_id )
+ @issue = Issue .find (issue_id )
+ @project = @issue .project
+ mail (to : @issue .assignee_email , subject : subject ("new issue ##{@issue.id}" , @issue .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_merge_request_email (merge_request_id)
+ click to toggle source
+
+
+
+
+
+
Merge Request
+
+
+
+
+
+def new_merge_request_email (merge_request_id )
+ @merge_request = MergeRequest .find (merge_request_id )
+ @project = @merge_request .project
+ mail (to : @merge_request .assignee_email , subject : subject ("new merge request !#{@merge_request.id}" , @merge_request .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_user_email (user_id, password)
+ click to toggle source
+
+
+
+
+
+
User
+
+
+
+
+
+def new_user_email (user_id , password )
+ @user = User .find (user_id )
+ @password = password
+ mail (to : @user .email , subject : subject ("Account was created for you" ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_commit_email (recipient_id, note_id)
+ click to toggle source
+
+
+
+
+
+
Note
+
+
+
+
+
+def note_commit_email (recipient_id , note_id )
+ @note = Note .find (note_id )
+ @commit = @note .noteable
+ @commit = CommitDecorator .decorate (@commit )
+ @project = @note .project
+ mail (to : recipient (recipient_id ), subject : subject ("note for commit #{@commit.short_id}" , @commit .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_issue_email (recipient_id, note_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def note_issue_email (recipient_id , note_id )
+ @note = Note .find (note_id )
+ @issue = @note .noteable
+ @project = @note .project
+ mail (to : recipient (recipient_id ), subject : subject ("note for issue ##{@issue.id}" ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_merge_request_email (recipient_id, note_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def note_merge_request_email (recipient_id , note_id )
+ @note = Note .find (note_id )
+ @merge_request = @note .noteable
+ @project = @note .project
+ mail (to : recipient (recipient_id ), subject : subject ("note for merge request !#{@merge_request.id}" ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_wall_email (recipient_id, note_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def note_wall_email (recipient_id , note_id )
+ @note = Note .find (note_id )
+ @project = @note .project
+ mail (to : recipient (recipient_id ), subject : subject )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ note_wiki_email (recipient_id, note_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def note_wiki_email (recipient_id , note_id )
+ @note = Note .find (note_id )
+ @wiki = @note .noteable
+ @project = @note .project
+ mail (to : recipient (recipient_id ), subject : subject ("note for wiki" ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_access_granted_email (user_project_id)
+ click to toggle source
+
+
+
+
+
+
Project
+
+
+
+
+
+def project_access_granted_email (user_project_id )
+ @users_project = UsersProject .find user_project_id
+ @project = @users_project .project
+ mail (to : @users_project .user .email ,
+ subject : subject ("access to project was granted" ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reassigned_issue_email (recipient_id, issue_id, previous_assignee_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reassigned_issue_email (recipient_id , issue_id , previous_assignee_id )
+ @issue = Issue .find (issue_id )
+ @previous_assignee ||= User .find (previous_assignee_id )
+ @project = @issue .project
+ mail (to : recipient (recipient_id ), subject : subject ("changed issue ##{@issue.id}" , @issue .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reassigned_merge_request_email (recipient_id, merge_request_id, previous_assignee_id)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reassigned_merge_request_email (recipient_id , merge_request_id , previous_assignee_id )
+ @merge_request = MergeRequest .find (merge_request_id )
+ @previous_assignee ||= User .find (previous_assignee_id )
+ @project = @merge_request .project
+ mail (to : recipient (recipient_id ), subject : subject ("changed merge request !#{@merge_request.id}" , @merge_request .title ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/OmniauthCallbacksController.html b/doc/app/OmniauthCallbacksController.html
new file mode 100644
index 00000000..d40a16a3
--- /dev/null
+++ b/doc/app/OmniauthCallbacksController.html
@@ -0,0 +1,527 @@
+
+
+
+
+
+
+class OmniauthCallbacksController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class OmniauthCallbacksController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ failure_message ()
+ click to toggle source
+
+
+
+
+
+
Extend the standard message generation to accept our custom exception
+
+
+
+
+
+def failure_message
+ exception = env ["omniauth.error" ]
+ error = exception .error_reason if exception .respond_to? (:error_reason )
+ error ||= exception .error if exception .respond_to? (:error )
+ error ||= exception .message if exception .respond_to? (:message )
+ error ||= env ["omniauth.error.type" ].to_s
+ error .to_s .humanize if error
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ldap ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ldap
+
+ @user = User .find_for_ldap_auth (request .env ["omniauth.auth" ], current_user )
+ if @user .persisted?
+ @user .remember_me = true
+ end
+ sign_in_and_redirect @user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/PostReceive.html b/doc/app/PostReceive.html
new file mode 100644
index 00000000..11468fd9
--- /dev/null
+++ b/doc/app/PostReceive.html
@@ -0,0 +1,495 @@
+
+
+
+
+
+
+class PostReceive - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class PostReceive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProfileController.html b/doc/app/ProfileController.html
new file mode 100644
index 00000000..deb4b0bc
--- /dev/null
+++ b/doc/app/ProfileController.html
@@ -0,0 +1,683 @@
+
+
+
+
+
+
+class ProfileController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProfileController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ design ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ history ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def history
+ @events = current_user .recent_events .page (params [:page ]).per (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ password_update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def password_update
+ params [:user ].reject! { | k , v | k != "password" && k != "password_confirmation" }
+
+ if @user .update_attributes (params [:user ])
+ flash [:notice ] = "Password was successfully updated. Please login with it"
+ redirect_to new_user_session_path
+ else
+ render action : "password"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ reset_private_token ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def reset_private_token
+ current_user .reset_authentication_token!
+ redirect_to profile_account_path
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ token ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @user .update_attributes (params [:user ])
+ redirect_to :back
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProfileHelper.html b/doc/app/ProfileHelper.html
new file mode 100644
index 00000000..ab7773ba
--- /dev/null
+++ b/doc/app/ProfileHelper.html
@@ -0,0 +1,481 @@
+
+
+
+
+
+
+module ProfileHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module ProfileHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ oauth_active_class (provider)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def oauth_active_class provider
+ if current_user .provider == provider .to_s
+ 'active'
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Project.html b/doc/app/Project.html
new file mode 100644
index 00000000..55868ef1
--- /dev/null
+++ b/doc/app/Project.html
@@ -0,0 +1,1202 @@
+
+
+
+
+
+
+class Project - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error_code [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ access_options ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def access_options
+ UsersProject .access_roles
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ active ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def active
+ joins (:issues , :notes , :merge_requests ).order ("issues.created_at, notes.created_at, merge_requests.created_at DESC" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create_by_user (params, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create_by_user (params , user )
+ project = Project .new params
+
+ Project .transaction do
+ project .owner = user
+ project .save!
+
+
+ project .users_projects .create! (project_access : UsersProject :: MASTER , user : user )
+
+
+
+ project .update_repository
+ end
+
+ project
+rescue Gitlab :: Gitolite :: AccessDenied => ex
+ project .error_code = :gitolite
+ project
+rescue => ex
+ project .error_code = :db
+ project .errors .add (:base , "Can't save project. Please try again later" )
+ project
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search (query)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search query
+ where ("name LIKE :query OR code LIKE :query OR path LIKE :query" , query : "%#{query}%" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build_commit_note (commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def build_commit_note (commit )
+ notes .new (noteable_id : commit .id , noteable_type : "Commit" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ check_limit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def check_limit
+ unless owner .can_create_project?
+ errors [:base ] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it" )
+ end
+rescue
+ errors [:base ] << ("Can't check your ability to create project" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit_line_notes (commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit_line_notes (commit )
+ notes .where (noteable_id : commit .id , noteable_type : "Commit" ).where ("line_code IS NOT NULL" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit_notes (commit)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit_notes (commit )
+ notes .where (noteable_id : commit .id , noteable_type : "Commit" , line_code : nil )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ common_notes ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def common_notes
+ notes .where (noteable_type : ["" , nil ]).inc_author_project
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ git_error? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def git_error?
+ error_code == :gitolite
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ issues_labels ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def issues_labels
+ issues .tag_counts_on (:labels )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_activity ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_activity
+ last_event
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_activity_date ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_activity_date
+ last_event .try (:created_at ) || updated_at
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def private?
+ private_flag
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_id ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_id
+ self .id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ public? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def public?
+ ! private_flag
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repo_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repo_name
+ if path == "gitolite-admin"
+ errors .add (:path , " like 'gitolite-admin' is not allowed" )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ saved? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def saved?
+ id && valid?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_param ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_param
+ code
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ web_url ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def web_url
+ [Gitlab .config .url , code ].join ("/" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wiki_notes ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def wiki_notes
+ Note .where (noteable_id : wikis .pluck (:id ), noteable_type : 'Wiki' , project_id : self .id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProjectHook.html b/doc/app/ProjectHook.html
new file mode 100644
index 00000000..e5d17ef0
--- /dev/null
+++ b/doc/app/ProjectHook.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class ProjectHook - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProjectHook
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProjectObserver.html b/doc/app/ProjectObserver.html
new file mode 100644
index 00000000..d4ce7824
--- /dev/null
+++ b/doc/app/ProjectObserver.html
@@ -0,0 +1,589 @@
+
+
+
+
+
+
+class ProjectObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProjectObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create project
+ log_info ("#{project.owner.name} created a new project \"#{project.name}\"" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_destroy (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_destroy (project )
+ log_info ("Project \"#{project.name}\" was removed" )
+
+ project .destroy_repository
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_save (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_save (project )
+ project .update_repository
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ log_info (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def log_info message
+ Gitlab :: AppLogger .info message
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProjectResourceController.html b/doc/app/ProjectResourceController.html
new file mode 100644
index 00000000..aa972617
--- /dev/null
+++ b/doc/app/ProjectResourceController.html
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+class ProjectResourceController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProjectResourceController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProjectsController.html b/doc/app/ProjectsController.html
new file mode 100644
index 00000000..6982deab
--- /dev/null
+++ b/doc/app/ProjectsController.html
@@ -0,0 +1,785 @@
+
+
+
+
+
+
+class ProjectsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProjectsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @project = Project .create_by_user (params [:project ], current_user )
+
+ respond_to do | format |
+ format .html do
+ if @project .saved?
+ redirect_to (@project , notice : 'Project was successfully created.' )
+ else
+ render action : "new"
+ end
+ end
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+
+
+ UsersProject .skip_callback (:destroy , :after , :update_repository )
+ project .destroy
+ UsersProject .set_callback (:destroy , :after , :update_repository )
+
+ respond_to do | format |
+ format .html { redirect_to root_path }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ files ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def files
+ @notes = @project .notes .where ("attachment != 'NULL'" ).order ("created_at DESC" ).limit (100 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ graph ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def graph
+ @days_json , @commits_json = Gitlab :: GraphCommit .to_graph (project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @project = Project .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ limit = (params [:limit ] || 20 ).to_i
+ @events = @project .events .recent .limit (limit ).offset (params [:offset ] || 0 )
+
+ respond_to do | format |
+ format .html do
+ unless @project .empty_repo?
+ @last_push = current_user .recent_push (@project .id )
+ render :show
+ else
+ render "projects/empty"
+ end
+ end
+ format .js
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ respond_to do | format |
+ if project .update_attributes (params [:project ])
+ format .html { redirect_to edit_project_path (project ), notice : 'Project was successfully updated.' }
+ format .js
+ else
+ format .html { render action : "edit" }
+ format .js
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ wall ()
+ click to toggle source
+
+
+
+
+
+
Wall
+
+
+
+
+
+def wall
+ return render_404 unless @project .wall_enabled
+ @note = Note .new
+
+ respond_to do | format |
+ format .html
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProjectsHelper.html b/doc/app/ProjectsHelper.html
new file mode 100644
index 00000000..5edd4592
--- /dev/null
+++ b/doc/app/ProjectsHelper.html
@@ -0,0 +1,543 @@
+
+
+
+
+
+
+module ProjectsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module ProjectsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ grouper_project_members (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def grouper_project_members (project )
+ @project .users_projects .sort_by (&:project_access ).reverse .group_by (&:project_access )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_to_project (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def link_to_project project
+ link_to project .name , project
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ remove_from_team_message (project, member)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def remove_from_team_message (project , member )
+ "You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProtectedBranch.html b/doc/app/ProtectedBranch.html
new file mode 100644
index 00000000..900646dc
--- /dev/null
+++ b/doc/app/ProtectedBranch.html
@@ -0,0 +1,529 @@
+
+
+
+
+
+
+class ProtectedBranch - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProtectedBranch
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit
+ project .commit (self .name )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_repository ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_repository
+ git_host .update_repository (project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/ProtectedBranchesController.html b/doc/app/ProtectedBranchesController.html
new file mode 100644
index 00000000..7eb2b1fd
--- /dev/null
+++ b/doc/app/ProtectedBranchesController.html
@@ -0,0 +1,556 @@
+
+
+
+
+
+
+class ProtectedBranchesController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class ProtectedBranchesController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @project .protected_branches .create (params [:protected_branch ])
+ redirect_to project_protected_branches_path (@project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @project .protected_branches .find (params [:id ]).destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_protected_branches_path }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @branches = @project .protected_branches .all
+ @protected_branch = @project .protected_branches .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/PushEvent.html b/doc/app/PushEvent.html
new file mode 100644
index 00000000..002866a6
--- /dev/null
+++ b/doc/app/PushEvent.html
@@ -0,0 +1,1105 @@
+
+
+
+
+
+
+module PushEvent - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module PushEvent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branch? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branch?
+ data [:ref ]["refs/heads" ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branch_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branch_name
+ @branch_name ||= data [:ref ].gsub ("refs/heads/" , "" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit_from ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit_from
+ data [:before ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit_to ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit_to
+ data [:after ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits ()
+ click to toggle source
+
+
+
+
+
+
Max 20 commits from push DESC
+
+
+
+
+
+def commits
+ @commits ||= data [:commits ].map { | commit | project .commit (commit [:id ]) }.reverse
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_count ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_count
+ data [:total_commits_count ] || commits .count || 0
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_commit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_commit
+ project .commit (commit_to )
+rescue => ex
+ nil
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_push_to_non_root? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_push_to_non_root?
+ branch? && project .default_branch != branch_name
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ md_ref? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def md_ref?
+ ! (rm_ref? || new_ref? )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_branch? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_branch?
+ commit_from =~ %r^00000/
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_ref? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_ref?
+ commit_from =~ %r^00000/
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ parent_commit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def parent_commit
+ project .commit (commit_from )
+rescue => ex
+ nil
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ push_action_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def push_action_name
+ if new_ref?
+ "pushed new"
+ elsif rm_ref?
+ "deleted"
+ else
+ "pushed to"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ push_with_commits? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def push_with_commits?
+ md_ref? && commits .any? && parent_commit && last_commit
+rescue Grit :: NoSuchPathError
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ref_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ref_name
+ if tag?
+ tag_name
+ else
+ branch_name
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ref_type ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ref_type
+ tag? ? "tag" : "branch"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rm_ref? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def rm_ref?
+ commit_to =~ %r^00000/
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tag?
+ data [:ref ]["refs/tags" ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag_name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tag_name
+ @tag_name ||= data [:ref ].gsub ("refs/tags/" , "" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ valid_push? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def valid_push?
+ data [:ref ]
+rescue => ex
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/PushObserver.html b/doc/app/PushObserver.html
new file mode 100644
index 00000000..804447a6
--- /dev/null
+++ b/doc/app/PushObserver.html
@@ -0,0 +1,699 @@
+
+
+
+
+
+
+module PushObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module PushObserver
+
+
+
+
Includes methods for handling Git Push events
+
+
Triggered by PostReceive job
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute_hooks (oldrev, newrev, ref, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute_hooks (oldrev , newrev , ref , user )
+ ref_parts = ref .split ('/' )
+
+
+ return if ref_parts [1 ] !~ %rheads/ || oldrev == "00000000000000000000000000000000"
+
+ data = post_receive_data (oldrev , newrev , ref , user )
+
+ hooks .each { | hook | hook .execute (data ) }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ observe_push (oldrev, newrev, ref, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def observe_push (oldrev , newrev , ref , user )
+ data = post_receive_data (oldrev , newrev , ref , user )
+
+ Event .create (
+ project : self ,
+ action : Event :: Pushed ,
+ data : data ,
+ author_id : data [:user_id ]
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ post_receive_data (oldrev, newrev, ref, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def post_receive_data (oldrev , newrev , ref , user )
+
+ push_commits = commits_between (oldrev , newrev )
+
+
+ push_commits_count = push_commits .size
+
+
+ push_commits_limited = push_commits .last (20 )
+
+
+ data = {
+ before : oldrev ,
+ after : newrev ,
+ ref : ref ,
+ user_id : user .id ,
+ user_name : user .name ,
+ repository : {
+ name : name ,
+ url : web_url ,
+ description : description ,
+ homepage : web_url ,
+ },
+ commits : [],
+ total_commits_count : push_commits_count
+ }
+
+
+
+
+ push_commits_limited .each do | commit |
+ data [:commits ] << {
+ id : commit .id ,
+ message : commit .safe_message ,
+ timestamp : commit .date .xmlschema ,
+ url : "#{Gitlab.config.url}/#{code}/commits/#{commit.id}" ,
+ author : {
+ name : commit .author_name ,
+ email : commit .author_email
+ }
+ }
+ end
+
+ data
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ trigger_post_receive (oldrev, newrev, ref, user)
+ click to toggle source
+
+
+
+
+
+
This method will be called after each post receive and only if the provided
+user is present in GitLab.
+
+
All callbacks for post receive should be placed here.
+
+
+
+
+
+def trigger_post_receive (oldrev , newrev , ref , user )
+
+ self .observe_push (oldrev , newrev , ref , user )
+
+
+ self .update_merge_requests (oldrev , newrev , ref , user )
+
+
+ self .execute_hooks (oldrev , newrev , ref , user )
+
+
+ self .satellite .create unless self .satellite .exists?
+
+
+
+ if default_branch .nil?
+ update_attributes (default_branch : discover_default_branch )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_merge_requests (oldrev, newrev, ref, user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_merge_requests (oldrev , newrev , ref , user )
+ return true unless ref =~ %rheads/
+ branch_name = ref .gsub ("refs/heads/" , "" )
+ c_ids = self .commits_between (oldrev , newrev ).map (&:id )
+
+
+ mrs = self .merge_requests .opened .find_all_by_branch (branch_name ).all
+ mrs .each { | merge_request | merge_request .reload_code ; merge_request .mark_as_unchecked }
+
+
+ mrs = self .merge_requests .opened .where (target_branch : branch_name ).all
+ mrs = mrs .select (&:last_commit ).select { | mr | c_ids .include? (mr .last_commit .id ) }
+ mrs .each { | merge_request | merge_request .merge! (user .id ) }
+
+ true
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Redcarpet.html b/doc/app/Redcarpet.html
new file mode 100644
index 00000000..238b7f25
--- /dev/null
+++ b/doc/app/Redcarpet.html
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+module Redcarpet - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Redcarpet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Redcarpet/Render.html b/doc/app/Redcarpet/Render.html
new file mode 100644
index 00000000..acb7ba3c
--- /dev/null
+++ b/doc/app/Redcarpet/Render.html
@@ -0,0 +1,432 @@
+
+
+
+
+
+
+module Redcarpet::Render - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Redcarpet::Render
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Redcarpet/Render/GitlabHTML.html b/doc/app/Redcarpet/Render/GitlabHTML.html
new file mode 100644
index 00000000..93212eab
--- /dev/null
+++ b/doc/app/Redcarpet/Render/GitlabHTML.html
@@ -0,0 +1,594 @@
+
+
+
+
+
+
+class Redcarpet::Render::GitlabHTML - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Redcarpet::Render::GitlabHTML
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ template [R]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (template, options = {})
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (template , options = {})
+ @template = template
+ @project = @template .instance_variable_get ("@project" )
+ super options
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ block_code (code, language)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def block_code (code , language )
+ if Pygments :: Lexer .find (language )
+ Pygments .highlight (code , lexer : language , options : {encoding : 'utf-8' })
+ else
+ Pygments .highlight (code , options : {encoding : 'utf-8' })
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ postprocess (full_document)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def postprocess (full_document )
+ h .gfm (full_document )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/RefsController.html b/doc/app/RefsController.html
new file mode 100644
index 00000000..a8248da0
--- /dev/null
+++ b/doc/app/RefsController.html
@@ -0,0 +1,638 @@
+
+
+
+
+
+
+class RefsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class RefsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ logs_tree ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def logs_tree
+ contents = @tree .contents
+ @logs = contents .map do | content |
+ file = params [:path ] ? File .join (params [:path ], content .name ) : content .name
+ last_commit = @project .commits (@commit .id , file , 1 ).last
+ last_commit = CommitDecorator .decorate (last_commit )
+ {
+ file_name : content .name ,
+ commit : last_commit
+ }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ switch ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def switch
+ respond_to do | format |
+ format .html do
+ new_path = if params [:destination ] == "tree"
+ project_tree_path (@project , @ref )
+ else
+ project_commits_path (@project , @ref )
+ end
+
+ redirect_to new_path
+ end
+ format .js do
+ @ref = params [:ref ]
+ define_tree_vars
+ render "tree"
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ define_tree_vars ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def define_tree_vars
+ params [:path ] = nil if params [:path ].blank?
+
+ @repo = project .repo
+ @commit = project .commit (@ref )
+ @commit = CommitDecorator .decorate (@commit )
+ @tree = Tree .new (@commit .tree , project , @ref , params [:path ])
+ @tree = TreeDecorator .new (@tree )
+ @hex_path = Digest :: SHA1 .hexdigest (params [:path ] || "" )
+
+ if params [:path ]
+ @logs_path = logs_file_project_ref_path (@project , @ref , params [:path ])
+ else
+ @logs_path = logs_tree_project_ref_path (@project , @ref )
+ end
+rescue
+ return render_404
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ref ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ref
+ @ref = params [:id ] || params [:ref ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/RepositoriesController.html b/doc/app/RepositoriesController.html
new file mode 100644
index 00000000..3a22f71e
--- /dev/null
+++ b/doc/app/RepositoriesController.html
@@ -0,0 +1,593 @@
+
+
+
+
+
+
+class RepositoriesController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class RepositoriesController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ archive ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def archive
+ unless can? (current_user , :download_code , @project )
+ render_404 and return
+ end
+
+
+ file_path = @project .archive_repo (params [:ref ])
+
+ if file_path
+
+ send_file file_path
+ else
+ render_404
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branches ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branches
+ @branches = @project .branches
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @activities = @project .commits_with_refs (20 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Repository.html b/doc/app/Repository.html
new file mode 100644
index 00000000..cb68146c
--- /dev/null
+++ b/doc/app/Repository.html
@@ -0,0 +1,1566 @@
+
+
+
+
+
+
+module Repository - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Repository
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ archive_repo (ref)
+ click to toggle source
+
+
+
+
+
+
Archive Project to .tar.gz
+
+
Already packed repo archives stored at
+app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
+
+
+
+
+
+def archive_repo (ref )
+ ref = ref || self .root_ref
+ commit = self .commit (ref )
+ return nil unless commit
+
+
+ file_name = self .code + "-" + commit .id .to_s + ".tar.gz"
+ storage_path = Rails .root .join ("tmp" , "repositories" , self .code )
+ file_path = File .join (storage_path , file_name )
+
+
+ prefix = self .code + "/"
+
+
+ unless File .exists? (file_path )
+ FileUtils .mkdir_p storage_path
+ file = self .repo .archive_to_file (ref , prefix , file_path )
+ end
+
+ file_path
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branch_names ()
+ click to toggle source
+
+
+
+
+
+
Returns an Array of branch names
+
+
+
+
+
+def branch_names
+ repo .branches .collect (&:name ).sort
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branches ()
+ click to toggle source
+
+
+
+
+
+
Returns an Array of Branches
+
+
+
+
+
+def branches
+ repo .branches .sort_by (&:name )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commit (commit_id = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commit (commit_id = nil )
+ Commit .find_or_first (repo , commit_id , root_ref )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits (ref, path = nil, limit = nil, offset = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits (ref , path = nil , limit = nil , offset = nil )
+ Commit .commits (repo , ref , path , limit , offset )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_between (from, to)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_between (from , to )
+ Commit .commits_between (repo , from , to )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_since (date)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_since (date )
+ Commit .commits_since (repo , date )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ commits_with_refs (n = 20)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def commits_with_refs (n = 20 )
+ Commit .commits_with_refs (repo , n )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy_repository ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy_repository
+ git_host .remove_repository (self )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ discover_default_branch ()
+ click to toggle source
+
+
+
+
+
+
Discovers the default branch based on the repository’s available branches
+
+If no branches are present, returns nil
+
+If one branch is present, returns its name
+
+If two or more branches are present, returns the one that has a name
+matching #root_ref
+(default_branch or ‘master’ if default_branch is nil)
+
+
+
+
+
+
+def discover_default_branch
+ if branch_names .length == 0
+ nil
+ elsif branch_names .length == 1
+ branch_names .first
+ else
+ branch_names .select { | v | v == root_ref }.first
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ empty_repo? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def empty_repo?
+ ! repo_exists? || ! has_commits?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fresh_commits (n = 10)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def fresh_commits (n = 10 )
+ Commit .fresh_commits (repo , n )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ has_commits? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def has_commits?
+ ! ! commit
+rescue Grit :: NoSuchPathError
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ has_post_receive_file? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def has_post_receive_file?
+ hook_file = File .join (path_to_repo , 'hooks' , 'post-receive' )
+ File .exists? (hook_file )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ heads ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def heads
+ @heads ||= repo .heads
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http_url_to_repo ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def http_url_to_repo
+ http_url = [Gitlab .config .url , "/" , path , ".git" ].join ('' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ last_commit_for (ref, path = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def last_commit_for (ref , path = nil )
+ commits (ref , path , 1 ).first
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ open_branches ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def open_branches
+ if protected_branches .empty?
+ self .repo .heads
+ else
+ pnames = protected_branches .map (&:name )
+ self .repo .heads .reject { | h | pnames .include? (h .name ) }
+ end .sort_by (&:name )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ path_to_repo ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def path_to_repo
+ File .join (Gitlab .config .git_base_path , "#{path}.git" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ protected_branch? (branch_name)
+ click to toggle source
+
+
+
+
+
+
Check if current branch name is marked as protected in the system
+
+
+
+
+
+def protected_branch? branch_name
+ protected_branches .map (&:name ).include? (branch_name )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ref_names ()
+ click to toggle source
+
+
+
+
+
+
Returns an Array of branch and tag names
+
+
+
+
+
+def ref_names
+ [branch_names + tag_names ].flatten
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repo ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repo
+ @repo ||= Grit :: Repo .new (path_to_repo )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repo_exists? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repo_exists?
+ @repo_exists ||= (repo && ! repo .branches .empty? )
+rescue
+ @repo_exists = false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ root_ref ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def root_ref
+ default_branch || "master"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ root_ref? (branch)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def root_ref? (branch )
+ root_ref == branch
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ satellite ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def satellite
+ @satellite ||= Gitlab :: Satellite .new (self )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ssh_url_to_repo ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def ssh_url_to_repo
+ url_to_repo
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag_names ()
+ click to toggle source
+
+
+
+
+
+
Returns an Array of tag names
+
+
+
+
+
+def tag_names
+ repo .tags .collect (&:name ).sort .reverse
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree (fcommit, path = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tree (fcommit , path = nil )
+ fcommit = commit if fcommit == :head
+ tree = fcommit .tree
+ path ? (tree / path ) : tree
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_repository ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_repository
+ git_host .update_repository (self )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ url_to_repo ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def url_to_repo
+ git_host .url_to_repo (path )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ valid_repo? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def valid_repo?
+ repo
+rescue
+ errors .add (:path , "Invalid repository path" )
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SearchContext.html b/doc/app/SearchContext.html
new file mode 100644
index 00000000..6a3d2bd5
--- /dev/null
+++ b/doc/app/SearchContext.html
@@ -0,0 +1,599 @@
+
+
+
+
+
+
+class SearchContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SearchContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ params [RW]
+
+
+
+
+
+
+
+
+
+
+
+ project_ids [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (project_ids, params)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (project_ids , params )
+ @project_ids , @params = project_ids , params .dup
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ query = params [:search ]
+
+ return result unless query .present?
+
+ result [:projects ] = Project .where (id : project_ids ).search (query ).limit (10 )
+ result [:merge_requests ] = MergeRequest .where (project_id : project_ids ).search (query ).limit (10 )
+ result [:issues ] = Issue .where (project_id : project_ids ).search (query ).limit (10 )
+ result
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ result ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def result
+ @result ||= {
+ projects : [],
+ merge_requests : [],
+ issues : []
+ }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SearchController.html b/doc/app/SearchController.html
new file mode 100644
index 00000000..0c14ea8f
--- /dev/null
+++ b/doc/app/SearchController.html
@@ -0,0 +1,489 @@
+
+
+
+
+
+
+class SearchController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SearchController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ result = SearchContext .new (current_user .project_ids , params ).execute
+
+ @projects = result [:projects ]
+ @merge_requests = result [:merge_requests ]
+ @issues = result [:issues ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Snippet.html b/doc/app/Snippet.html
new file mode 100644
index 00000000..a24e4494
--- /dev/null
+++ b/doc/app/Snippet.html
@@ -0,0 +1,667 @@
+
+
+
+
+
+
+class Snippet - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Snippet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ content_types ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .content_types
+ [
+ ".rb" , ".py" , ".pl" , ".scala" , ".c" , ".cpp" , ".java" ,
+ ".haml" , ".html" , ".sass" , ".scss" , ".xml" , ".php" , ".erb" ,
+ ".js" , ".sh" , ".coffee" , ".yml" , ".md"
+ ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ data ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def data
+ content
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ expired? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def expired?
+ expires_at && expires_at < Time .current
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mode ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ name ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def name
+ file_name
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ size ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SnippetsController.html b/doc/app/SnippetsController.html
new file mode 100644
index 00000000..7585a295
--- /dev/null
+++ b/doc/app/SnippetsController.html
@@ -0,0 +1,833 @@
+
+
+
+
+
+
+class SnippetsController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SnippetsController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @snippet = @project .snippets .new (params [:snippet ])
+ @snippet .author = current_user
+ @snippet .save
+
+ if @snippet .valid?
+ redirect_to [@project , @snippet ]
+ else
+ respond_with (@snippet )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ return access_denied! unless can? (current_user , :admin_snippet , @snippet )
+
+ @snippet .destroy
+
+ redirect_to project_snippets_path (@project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def index
+ @snippets = @project .snippets
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @snippet = @project .snippets .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ raw ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def raw
+ send_data (
+ @snippet .content ,
+ type : "text/plain" ,
+ disposition : 'inline' ,
+ filename : @snippet .file_name
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @note = @project .notes .new (noteable : @snippet )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @snippet .update_attributes (params [:snippet ])
+
+ if @snippet .valid?
+ redirect_to [@project , @snippet ]
+ else
+ respond_with (@snippet )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_admin_snippet! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_admin_snippet!
+ return render_404 unless can? (current_user , :admin_snippet , @snippet )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ authorize_modify_snippet! ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def authorize_modify_snippet!
+ return render_404 unless can? (current_user , :modify_snippet , @snippet )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ snippet ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def snippet
+ @snippet ||= @project .snippets .find (params [:id ])
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SnippetsHelper.html b/doc/app/SnippetsHelper.html
new file mode 100644
index 00000000..99c08d51
--- /dev/null
+++ b/doc/app/SnippetsHelper.html
@@ -0,0 +1,485 @@
+
+
+
+
+
+
+module SnippetsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module SnippetsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lifetime_select_options ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def lifetime_select_options
+ options = [
+ ['forever' , nil ],
+ ['1 day' , "#{Date.current + 1.day}" ],
+ ['1 week' , "#{Date.current + 1.week}" ],
+ ['1 month' , "#{Date.current + 1.month}" ]
+ ]
+ options_for_select (options )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/StaticModel.html b/doc/app/StaticModel.html
new file mode 100644
index 00000000..9dd1617c
--- /dev/null
+++ b/doc/app/StaticModel.html
@@ -0,0 +1,648 @@
+
+
+
+
+
+
+module StaticModel - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module StaticModel
+
+
+
+
Provides an ActiveRecord-like interface to a model whose data is not
+persisted to a database.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ == (other)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def == (other )
+ if other .is_a? StaticModel
+ id == other .id
+ else
+ super
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [] (key)
+ click to toggle source
+
+
+
+
+
+
Used by AR for fetching attributes
+
+
Pass it along if we respond to it.
+
+
+
+
+
+def [] (key )
+ send (key ) if respond_to? (key )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroyed? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroyed?
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new_record? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new_record?
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ persisted? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def persisted?
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_param ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_param
+ id
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/StaticModel/ClassMethods.html b/doc/app/StaticModel/ClassMethods.html
new file mode 100644
index 00000000..27ee1373
--- /dev/null
+++ b/doc/app/StaticModel/ClassMethods.html
@@ -0,0 +1,511 @@
+
+
+
+
+
+
+module StaticModel::ClassMethods - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module StaticModel::ClassMethods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ base_class ()
+ click to toggle source
+
+
+
+
+
+
Used by ActiveRecord’s polymorphic association to set object_type
+
+
+
+
+
+def base_class
+ self
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ primary_key ()
+ click to toggle source
+
+
+
+
+
+
Used by ActiveRecord’s polymorphic association to set object_id
+
+
+
+
+
+def primary_key
+ 'id'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SystemHook.html b/doc/app/SystemHook.html
new file mode 100644
index 00000000..8e35bf27
--- /dev/null
+++ b/doc/app/SystemHook.html
@@ -0,0 +1,525 @@
+
+
+
+
+
+
+class SystemHook - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SystemHook
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all_hooks_fire (data)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .all_hooks_fire (data )
+ SystemHook .all .each do | sh |
+ sh .async_execute data
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ async_execute (data)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def async_execute (data )
+ Resque .enqueue (SystemHookWorker , id , data )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SystemHookObserver.html b/doc/app/SystemHookObserver.html
new file mode 100644
index 00000000..20d81963
--- /dev/null
+++ b/doc/app/SystemHookObserver.html
@@ -0,0 +1,573 @@
+
+
+
+
+
+
+class SystemHookObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SystemHookObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (model)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (model )
+ if model .kind_of? Project
+ SystemHook .all_hooks_fire ({
+ event_name : "project_create" ,
+ name : model .name ,
+ path : model .path ,
+ project_id : model .id ,
+ owner_name : model .owner .name ,
+ owner_email : model .owner .email ,
+ created_at : model .created_at
+ })
+ elsif model .kind_of? User
+ SystemHook .all_hooks_fire ({
+ event_name : "user_create" ,
+ name : model .name ,
+ email : model .email ,
+ created_at : model .created_at
+ })
+
+ elsif model .kind_of? UsersProject
+ SystemHook .all_hooks_fire ({
+ event_name : "user_add_to_team" ,
+ project_name : model .project .name ,
+ project_path : model .project .path ,
+ project_id : model .project_id ,
+ user_name : model .user .name ,
+ user_email : model .user .email ,
+ project_access : model .repo_access_human ,
+ created_at : model .created_at
+ })
+
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_destroy (model)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_destroy (model )
+ if model .kind_of? Project
+ SystemHook .all_hooks_fire ({
+ event_name : "project_destroy" ,
+ name : model .name ,
+ path : model .path ,
+ project_id : model .id ,
+ owner_name : model .owner .name ,
+ owner_email : model .owner .email ,
+ })
+ elsif model .kind_of? User
+ SystemHook .all_hooks_fire ({
+ event_name : "user_destroy" ,
+ name : model .name ,
+ email : model .email
+ })
+
+ elsif model .kind_of? UsersProject
+ SystemHook .all_hooks_fire ({
+ event_name : "user_remove_from_team" ,
+ project_name : model .project .name ,
+ project_path : model .project .path ,
+ project_id : model .project_id ,
+ user_name : model .user .name ,
+ user_email : model .user .email ,
+ project_access : model .repo_access_human
+ })
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/SystemHookWorker.html b/doc/app/SystemHookWorker.html
new file mode 100644
index 00000000..153eb577
--- /dev/null
+++ b/doc/app/SystemHookWorker.html
@@ -0,0 +1,485 @@
+
+
+
+
+
+
+class SystemHookWorker - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class SystemHookWorker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TabHelper.html b/doc/app/TabHelper.html
new file mode 100644
index 00000000..43cc08a4
--- /dev/null
+++ b/doc/app/TabHelper.html
@@ -0,0 +1,621 @@
+
+
+
+
+
+
+module TabHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module TabHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ branches_tab_class ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def branches_tab_class
+ if current_page? (branches_project_repository_path (@project )) ||
+ current_controller? (:protected_branches ) ||
+ current_page? (project_repository_path (@project ))
+ 'active'
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nav_link (options = {}, &block)
+ click to toggle source
+
+
+
+
+
+
Navigation link helper
+
+
Returns an `li` element with an ‘active’ class if the supplied
+controller(s) and/or action(s) are currently active. The content of the
+element is the value passed to the block.
+
+
options - The options hash used to determine if the element is “active”
+(default: {})
+
+
:controller - One or more controller names to check (optional).
+:action - One or more action names to check (optional).
+:path - A shorthand path, such as 'dashboard#index', to check (optional).
+:html_options - Extra options to be passed to the list element (optional).
+
+
block - An optional block that will become the contents of the returned
+
+
`li` element.
+
+
When both :controller and :action are specified, BOTH must match in order
+to be marked as active. When only one is given, either can match.
+
+
Examples
+
+
+
+
+nav_link (controller : [:tree , :refs ], action : :edit ) { "Hello" }
+
+
+
+nav_link (controller : [:tree , :refs ]) { "Hello" }
+
+
+
+nav_link (path : 'tree#show' ) { "Hello" }
+
+
+
+nav_link (controller : :tree , html_options : {class : 'home' }) { "Hello" }
+
+
+
+
Returns a list item element String
+
+
+
+
+
+def nav_link (options = {}, &block )
+ if path = options .delete (:path )
+ c , a , _ = path .split ('#' )
+ else
+ c = options .delete (:controller )
+ a = options .delete (:action )
+ end
+
+ if c && a
+
+ klass = current_controller? (*c ) && current_action? (*a ) ? 'active' : ''
+ else
+
+ klass = current_controller? (*c ) || current_action? (*a ) ? 'active' : ''
+ end
+
+
+
+ o = options .delete (:html_options ) || {}
+ o [:class ] ||= ''
+ o [:class ] += ' ' + klass
+ o [:class ].strip!
+
+ if block_given?
+ content_tag (:li , capture (&block ), o )
+ else
+ content_tag (:li , nil , o )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_tab_class ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_tab_class
+ [:show , :files , :edit , :update ].each do | action |
+ return "active" if current_page? (controller : "projects" , action : action , id : @project )
+ end
+
+ if ['snippets' , 'hooks' , 'deploy_keys' , 'team_members' ].include? controller .controller_name
+ "active"
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TagsHelper.html b/doc/app/TagsHelper.html
new file mode 100644
index 00000000..3a98d61f
--- /dev/null
+++ b/doc/app/TagsHelper.html
@@ -0,0 +1,516 @@
+
+
+
+
+
+
+module TagsHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module TagsHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag_list (project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tag_list project
+ html = ''
+ project .tag_list .each do | tag |
+ html += link_to tag , tag_path (tag )
+ end
+
+ html .html_safe
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tag_path (tag)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tag_path tag
+ "/tags/#{tag}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Team.html b/doc/app/Team.html
new file mode 100644
index 00000000..3a583694
--- /dev/null
+++ b/doc/app/Team.html
@@ -0,0 +1,710 @@
+
+
+
+
+
+
+module Team - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Team
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_user_id_to_team (user_id, access_role)
+ click to toggle source
+
+
+
+
+
+
Add user to project with passed access role by user id
+
+
+
+
+
+def add_user_id_to_team (user_id , access_role )
+ users_projects .create (
+ user_id : user_id ,
+ project_access : access_role
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_user_to_team (user, access_role)
+ click to toggle source
+
+
+
+
+
+
Add user to project with passed access role
+
+
+
+
+
+def add_user_to_team (user , access_role )
+ add_user_id_to_team (user .id , access_role )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_users_ids_to_team (users_ids, access_role)
+ click to toggle source
+
+
+
+
+
+
Add multiple users to project with same access role by user ids
+
+
+
+
+
+def add_users_ids_to_team (users_ids , access_role )
+ UsersProject .bulk_import (self , users_ids , access_role )
+ self .update_repository
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ add_users_to_team (users, access_role)
+ click to toggle source
+
+
+
+
+
+
Add multiple users to project with same access role
+
+
+
+
+
+def add_users_to_team (users , access_role )
+ add_users_ids_to_team (users .map (&:id ), access_role )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ delete_users_ids_from_team (users_ids)
+ click to toggle source
+
+
+
+
+
+
Delete multiple users from project by user ids
+
+
+
+
+
+def delete_users_ids_from_team (users_ids )
+ UsersProject .bulk_delete (self , users_ids )
+ self .update_repository
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ team_member_by_id (user_id)
+ click to toggle source
+
+
+
+
+
+
Get Team Member record by user id
+
+
+
+
+
+def team_member_by_id (user_id )
+ users_projects .find_by_user_id (user_id )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ team_member_by_name_or_email (name = nil, email = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def team_member_by_name_or_email (name = nil , email = nil )
+ user = users .where ("name like ? or email like ?" , name , email ).first
+ users_projects .where (user : user ) if user
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_users_ids_to_role (users_ids, access_role)
+ click to toggle source
+
+
+
+
+
+
Update multiple project users to same access role by user ids
+
+
+
+
+
+def update_users_ids_to_role (users_ids , access_role )
+ UsersProject .bulk_update (self , users_ids , access_role )
+ self .update_repository
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TeamMembersController.html b/doc/app/TeamMembersController.html
new file mode 100644
index 00000000..46af7c9f
--- /dev/null
+++ b/doc/app/TeamMembersController.html
@@ -0,0 +1,698 @@
+
+
+
+
+
+
+class TeamMembersController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class TeamMembersController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ apply_import ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def apply_import
+ giver = Project .find (params [:source_project_id ])
+ status = UsersProject .import_team (giver , project )
+ notice = status ? "Succesfully imported" : "Import failed"
+
+ redirect_to project_team_members_path (project ), notice : notice
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @project .add_users_ids_to_team (
+ params [:user_ids ],
+ params [:project_access ]
+ )
+
+ redirect_to project_team_index_path (@project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @team_member = project .users_projects .find (params [:id ])
+ @team_member .destroy
+
+ respond_to do | format |
+ format .html { redirect_to project_team_index_path (@project ) }
+ format .js { render nothing : true }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def new
+ @team_member = project .users_projects .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @team_member = project .users_projects .find (params [:id ])
+ @events = @team_member .user .recent_events .where (:project_id => @project .id ).limit (7 )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ @team_member = project .users_projects .find (params [:id ])
+ @team_member .update_attributes (params [:team_member ])
+
+ unless @team_member .valid?
+ flash [:alert ] = "User should have at least one role"
+ end
+ redirect_to project_team_index_path (@project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TestHookContext.html b/doc/app/TestHookContext.html
new file mode 100644
index 00000000..e18701cb
--- /dev/null
+++ b/doc/app/TestHookContext.html
@@ -0,0 +1,488 @@
+
+
+
+
+
+
+class TestHookContext - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class TestHookContext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute
+ hook = project .hooks .find (params [:id ])
+ commits = project .commits (project .default_branch , nil , 3 )
+ data = project .post_receive_data (commits .last .id , commits .first .id , "refs/heads/#{project.default_branch}" , current_user )
+ hook .execute (data )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Tree.html b/doc/app/Tree.html
new file mode 100644
index 00000000..f1f414a4
--- /dev/null
+++ b/doc/app/Tree.html
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+class Tree - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ path [RW]
+
+
+
+
+
+
+
+
+
+
+
+ project [RW]
+
+
+
+
+
+
+
+
+
+
+
+ ref [RW]
+
+
+
+
+
+
+
+
+
+
+
+ tree [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ new (raw_tree, project, ref = nil, path = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def initialize (raw_tree , project , ref = nil , path = nil )
+ @project , @ref , @path = project , ref , path
+ @tree = if path .present?
+ raw_tree / path .dup .force_encoding ('ascii-8bit' )
+ else
+ raw_tree
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ empty? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def empty?
+ data .blank?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ invalid? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def invalid?
+ tree .nil?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is_blob? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def is_blob?
+ tree .is_a? (Grit :: Blob )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TreeController.html b/doc/app/TreeController.html
new file mode 100644
index 00000000..1adba0ec
--- /dev/null
+++ b/doc/app/TreeController.html
@@ -0,0 +1,583 @@
+
+
+
+
+
+
+class TreeController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class TreeController
+
+
+
+
Controller for viewing a repository’s file structure
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ @last_commit = @project .last_commit_for (@ref , @path ).sha
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ @hex_path = Digest :: SHA1 .hexdigest (@path )
+ @logs_path = logs_file_project_ref_path (@project , @ref , @path )
+
+ respond_to do | format |
+ format .html
+
+ format .js { no_cache_headers }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update
+ file_editor = Gitlab :: FileEditor .new (current_user , @project , @ref )
+ update_status = file_editor .update (
+ @path ,
+ params [:content ],
+ params [:commit_message ],
+ params [:last_commit ]
+ )
+
+ if update_status
+ redirect_to project_tree_path (@project , @id ), notice : "Your changes have been successfully commited"
+ else
+ flash [:notice ] = "Your changes could not be commited, because the file has been changed"
+ render :edit
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TreeDecorator.html b/doc/app/TreeDecorator.html
new file mode 100644
index 00000000..e6bdc0fa
--- /dev/null
+++ b/doc/app/TreeDecorator.html
@@ -0,0 +1,597 @@
+
+
+
+
+
+
+class TreeDecorator - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class TreeDecorator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ breadcrumbs (max_links = 2) { |link_to("..", "| ... }
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def breadcrumbs (max_links = 2 )
+ if path
+ part_path = ""
+ parts = path .split ("\/" )
+
+
+
+ yield (h .link_to (".." , "#" , remote : true )) if parts .count > max_links
+
+ parts .each do | part |
+ part_path = File .join (part_path , part ) unless part_path .empty?
+ part_path = part if part_path .empty?
+
+ next unless parts .last (2 ).include? (part ) if parts .count > max_links
+ yield (h .link_to (h .truncate (part , length : 40 ), h .project_tree_path (project , h .tree_join (ref , part_path )), remote : true ))
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ readme ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def readme
+ @readme ||= contents .find { | c | c .is_a? (Grit :: Blob ) and c .name =~ %r^readme/ }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ up_dir? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def up_dir?
+ path .present?
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ up_dir_path ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def up_dir_path
+ file = File .join (path , ".." )
+ h .project_tree_path (project , h .tree_join (ref , file ))
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/TreeHelper.html b/doc/app/TreeHelper.html
new file mode 100644
index 00000000..e185ba72
--- /dev/null
+++ b/doc/app/TreeHelper.html
@@ -0,0 +1,736 @@
+
+
+
+
+
+
+module TreeHelper - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module TreeHelper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ allowed_tree_edit? ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def allowed_tree_edit?
+ if @project .protected_branch? @ref
+ can? (current_user , :push_code_to_protected_branches , @project )
+ else
+ can? (current_user , :push_code , @project )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gitlab_markdown? (filename)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def gitlab_markdown? (filename )
+ filename .end_with? (*%w(.mdown .md .markdown) )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ markup? (filename)
+ click to toggle source
+
+
+
+
+
+
Public: Determines if a given filename is compatible with GitHub::Markup.
+
+
filename - Filename string to check
+
+
Returns boolean
+
+
+
+
+
+def markup? (filename )
+ filename .end_with? (*%w(.textile .rdoc .org .creole
+ .mediawiki .rst .asciidoc .pod) )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ plain_text_readme? (filename)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def plain_text_readme? filename
+ filename == 'README'
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ render_tree (contents)
+ click to toggle source
+
+
+
+
+
+
Sorts a repository’s tree so that folders are before files and renders
+their corresponding partials
+
+
contents - A Grit::Tree object for the current tree
+
+
+
+
+
+def render_tree (contents )
+
+ folders , files = contents .partition { | v | v .kind_of? (Grit :: Tree ) }
+
+ tree = ""
+
+
+ tree += render partial : 'tree/tree_item' , collection : folders , locals : {type : 'folder' } if folders .present?
+
+ files .each do | f |
+ if f .respond_to? (:url )
+
+ tree += render partial : 'tree/submodule_item' , object : f
+ else
+
+ tree += render partial : 'tree/tree_item' , object : f , locals : {type : 'file' }
+ end
+ end
+
+ tree .html_safe
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_hex_class (content)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def tree_hex_class (content )
+ "file_#{hexdigest(content.name)}"
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_icon (type)
+ click to toggle source
+
+
+
+
+
+
Return an image icon depending on the file type
+
+
type - String type of the tree item; either ‘folder’ or ‘file’
+
+
+
+
+
+def tree_icon (type )
+ image = type == 'folder' ? 'file_dir.png' : 'file_txt.png'
+ image_tag (image , size : '16x16' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tree_join (*args)
+ click to toggle source
+
+
+
+
+
+
Simple shortcut to File.join
+
+
+
+
+
+def tree_join (*args )
+ File .join (*args )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/User.html b/doc/app/User.html
new file mode 100644
index 00000000..513f9644
--- /dev/null
+++ b/doc/app/User.html
@@ -0,0 +1,755 @@
+
+
+
+
+
+
+class User - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class User
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ force_random_password [RW]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create_from_omniauth (auth, ldap = false)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create_from_omniauth (auth , ldap = false )
+ gitlab_auth .create_from_omniauth (auth , ldap )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ filter (filter_name)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def filter filter_name
+ case filter_name
+ when "admins" ; self .admins
+ when "blocked" ; self .blocked
+ when "wop" ; self .without_projects
+ else
+ self .active
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_for_ldap_auth (auth, signed_in_resource = nil)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def find_for_ldap_auth (auth , signed_in_resource = nil )
+ gitlab_auth .find_for_ldap_auth (auth , signed_in_resource )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ find_or_new_for_omniauth (auth)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def find_or_new_for_omniauth (auth )
+ gitlab_auth .find_or_new_for_omniauth (auth )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gitlab_auth ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def gitlab_auth
+ Gitlab :: Auth .new
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ search (query)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def search query
+ where ("name LIKE :query or email LIKE :query" , query : "%#{query}%" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ without_projects ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def without_projects
+ where ('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)' )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generate_password ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def generate_password
+ if self .force_random_password
+ self .password = self .password_confirmation = Devise .friendly_token .first (8 )
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/UserObserver.html b/doc/app/UserObserver.html
new file mode 100644
index 00000000..95c7249d
--- /dev/null
+++ b/doc/app/UserObserver.html
@@ -0,0 +1,557 @@
+
+
+
+
+
+
+class UserObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class UserObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (user )
+ log_info ("User \"#{user.name}\" (#{user.email}) was created" )
+
+ Notify .new_user_email (user .id , user .password ).deliver
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_destroy (user)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_destroy user
+ log_info ("User \"#{user.name}\" (#{user.email}) was removed" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ log_info (message)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def log_info message
+ Gitlab :: AppLogger .info message
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/UsersProject.html b/doc/app/UsersProject.html
new file mode 100644
index 00000000..f157832b
--- /dev/null
+++ b/doc/app/UsersProject.html
@@ -0,0 +1,904 @@
+
+
+
+
+
+
+class UsersProject - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class UsersProject
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DEVELOPER
+
+
+
+
+ GUEST
+
+
+
+
+ MASTER
+
+
+
+
+ REPORTER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ access_roles ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def access_roles
+ {
+ "Guest" => GUEST ,
+ "Reporter" => REPORTER ,
+ "Developer" => DEVELOPER ,
+ "Master" => MASTER
+ }
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bulk_delete (project, user_ids)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def bulk_delete (project , user_ids )
+ UsersProject .transaction do
+ UsersProject .where (:user_id => user_ids , :project_id => project .id ).each do | users_project |
+ users_project .destroy
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bulk_import (project, user_ids, project_access)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def bulk_import (project , user_ids , project_access )
+ UsersProject .transaction do
+ user_ids .each do | user_id |
+ users_project = UsersProject .new (
+ project_access : project_access ,
+ user_id : user_id
+ )
+ users_project .project = project
+ users_project .save
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bulk_update (project, user_ids, project_access)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def bulk_update (project , user_ids , project_access )
+ UsersProject .transaction do
+ UsersProject .where (:user_id => user_ids , :project_id => project .id ).each do | users_project |
+ users_project .project_access = project_access
+ users_project .save
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ import_team (source_project, target_project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def import_team (source_project , target_project )
+ UsersProject .without_repository_callback do
+ UsersProject .transaction do
+ team = source_project .users_projects .all
+
+ team .each do | tm |
+
+ next if target_project .users .include? (tm .user )
+
+ new_tm = tm .dup
+ new_tm .id = nil
+ new_tm .project_id = target_project .id
+ new_tm .save
+ end
+ end
+ end
+
+ target_project .update_repository
+ true
+rescue
+ false
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ user_bulk_import (user, project_ids, project_access)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def user_bulk_import (user , project_ids , project_access )
+ UsersProject .transaction do
+ project_ids .each do | project_id |
+ users_project = UsersProject .new (
+ project_access : project_access ,
+ )
+ users_project .project_id = project_id
+ users_project .user_id = user .id
+ users_project .save
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ without_repository_callback () { || ... }
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def without_repository_callback
+ UsersProject .skip_callback (:destroy , :after , :update_repository )
+ yield
+ UsersProject .set_callback (:destroy , :after , :update_repository )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ project_access_human ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def project_access_human
+ Project .access_options .key (self .project_access )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ repo_access_human ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def repo_access_human
+ self .class .access_roles .invert [self .project_access ]
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ role_access ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def role_access
+ project_access
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ update_repository ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def update_repository
+ git_host .update_repository (project )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/UsersProjectObserver.html b/doc/app/UsersProjectObserver.html
new file mode 100644
index 00000000..7c7b90a0
--- /dev/null
+++ b/doc/app/UsersProjectObserver.html
@@ -0,0 +1,558 @@
+
+
+
+
+
+
+class UsersProjectObserver - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class UsersProjectObserver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_commit (users_project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_commit (users_project )
+ return if users_project .destroyed?
+ Notify .project_access_granted_email (users_project .id ).deliver
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_create (users_project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_create (users_project )
+ Event .create (
+ project_id : users_project .project .id ,
+ action : Event :: Joined ,
+ author_id : users_project .user .id
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ after_destroy (users_project)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def after_destroy (users_project )
+ Event .create (
+ project_id : users_project .project .id ,
+ action : Event :: Left ,
+ author_id : users_project .user .id
+ )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Votes.html b/doc/app/Votes.html
new file mode 100644
index 00000000..9fa2a0b7
--- /dev/null
+++ b/doc/app/Votes.html
@@ -0,0 +1,615 @@
+
+
+
+
+
+
+module Votes - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
module Votes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ downvotes ()
+ click to toggle source
+
+
+
+
+
+
Return the number of -1 comments (downvotes)
+
+
+
+
+
+def downvotes
+ notes .select (&:downvote? ).size
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ downvotes_in_percent ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def downvotes_in_percent
+ if votes_count .zero?
+ 0
+ else
+ 100.0 - upvotes_in_percent
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ upvotes ()
+ click to toggle source
+
+
+
+
+
+
Return the number of +1 comments (upvotes)
+
+
+
+
+
+def upvotes
+ notes .select (&:upvote? ).size
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ upvotes_in_percent ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def upvotes_in_percent
+ if votes_count .zero?
+ 0
+ else
+ 100.0 / votes_count * upvotes
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ votes_count ()
+ click to toggle source
+
+
+
+
+
+
Return the total number of votes
+
+
+
+
+
+def votes_count
+ upvotes + downvotes
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/WebHook.html b/doc/app/WebHook.html
new file mode 100644
index 00000000..44a89adb
--- /dev/null
+++ b/doc/app/WebHook.html
@@ -0,0 +1,506 @@
+
+
+
+
+
+
+class WebHook - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class WebHook
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ execute (data)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def execute (data )
+ parsed_url = URI .parse (url )
+ if parsed_url .userinfo .blank?
+ WebHook .post (url , body : data .to_json , headers : { "Content-Type" => "application/json" })
+ else
+ post_url = url .gsub ("#{parsed_url.userinfo}@" , "" )
+ WebHook .post (post_url ,
+ body : data .to_json ,
+ headers : {"Content-Type" => "application/json" },
+ basic_auth : {username : parsed_url .user , password : parsed_url .password })
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/Wiki.html b/doc/app/Wiki.html
new file mode 100644
index 00000000..c2bf5b61
--- /dev/null
+++ b/doc/app/Wiki.html
@@ -0,0 +1,567 @@
+
+
+
+
+
+
+class Wiki - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class Wiki
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ regenerate_from (wiki)
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def self .regenerate_from wiki
+ regenerated_field = [:slug , :content , :title ]
+
+ new_wiki = Wiki .new
+ regenerated_field .each do | field |
+ new_wiki .send ("#{field}=" , wiki .send (field ))
+ end
+ new_wiki
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ to_param ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def to_param
+ slug
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ set_slug ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def set_slug
+ self .slug = self .title .parameterize
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/WikisController.html b/doc/app/WikisController.html
new file mode 100644
index 00000000..4a4e930c
--- /dev/null
+++ b/doc/app/WikisController.html
@@ -0,0 +1,676 @@
+
+
+
+
+
+
+class WikisController - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
class WikisController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def create
+ @wiki = @project .wikis .new (params [:wiki ])
+ @wiki .user = current_user
+
+ respond_to do | format |
+ if @wiki .save
+ format .html { redirect_to [@project , @wiki ], notice : 'Wiki was successfully updated.' }
+ else
+ format .html { render action : "edit" }
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ destroy ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def destroy
+ @wikis = @project .wikis .where (slug : params [:id ]).delete_all
+
+ respond_to do | format |
+ format .html { redirect_to project_wiki_path (@project , :index ), notice : "Page was successfully deleted" }
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ edit ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def edit
+ @wiki = @project .wikis .where (slug : params [:id ]).order ("created_at" ).last
+ @wiki = Wiki .regenerate_from @wiki
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ history ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def history
+ @wikis = @project .wikis .where (slug : params [:id ]).order ("created_at" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pages ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def pages
+ @wikis = @project .wikis .group (:slug ).order ("created_at" )
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+ show ()
+ click to toggle source
+
+
+
+
+
+
+
+
+
+
+
+def show
+ if params [:old_page_id ]
+ @wiki = @project .wikis .find (params [:old_page_id ])
+ else
+ @wiki = @project .wikis .where (slug : params [:id ]).order ("created_at" ).last
+ end
+
+ @note = @project .notes .new (noteable : @wiki )
+
+ if @wiki
+ render 'show'
+ else
+ if can? (current_user , :write_wiki , @project )
+ @wiki = @project .wikis .new (slug : params [:id ])
+ render 'edit'
+ else
+ render 'empty'
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/app/created.rid b/doc/app/created.rid
new file mode 100644
index 00000000..972a7e6f
--- /dev/null
+++ b/doc/app/created.rid
@@ -0,0 +1,135 @@
+Thu, 25 Oct 2012 11:45:21 +0300
+doc/README_FOR_APP Wed, 06 Jun 2012 13:56:49 +0300
+app/observers/issue_observer.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/observers/key_observer.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/observers/project_observer.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/observers/activity_observer.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/observers/user_observer.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/observers/merge_request_observer.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/observers/note_observer.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/observers/system_hook_observer.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/observers/users_project_observer.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/contexts/test_hook_context.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/contexts/commit_load_context.rb Mon, 22 Oct 2012 16:08:19 +0300
+app/contexts/notes/create_context.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/contexts/notes/load_context.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/contexts/search_context.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/contexts/issues_bulk_update_context.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/contexts/base_context.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/contexts/merge_requests_load_context.rb Mon, 22 Oct 2012 16:08:19 +0300
+app/contexts/issues_list_context.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/mailers/notify.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/team.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/push_event.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/votes.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/roles/issue_commonality.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/git_host.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/roles/authority.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/push_observer.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/roles/account.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/static_model.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/roles/repository.rb Wed, 24 Oct 2012 12:43:00 +0300
+app/workers/post_receive.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/workers/system_hook_worker.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/controllers/issues_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/labels_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/project_resource_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/dashboard_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/projects_controller.rb Tue, 23 Oct 2012 11:29:23 +0300
+app/controllers/repositories_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/milestones_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/hooks_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/blob_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/merge_requests_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/admin/logs_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/admin/dashboard_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/admin/projects_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/admin/hooks_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/admin/team_members_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/admin/groups_controller.rb Wed, 24 Oct 2012 12:43:00 +0300
+app/controllers/admin/users_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/admin/resque_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/blame_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/keys_controller.rb Wed, 26 Sep 2012 13:10:32 +0300
+app/controllers/admin_controller.rb Wed, 26 Sep 2012 13:10:32 +0300
+app/controllers/errors_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/help_controller.rb Wed, 06 Jun 2012 13:56:49 +0300
+app/controllers/profile_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/commits_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/team_members_controller.rb Wed, 24 Oct 2012 16:14:03 +0300
+app/controllers/omniauth_callbacks_controller.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/controllers/protected_branches_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/snippets_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/groups_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/compare_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/wikis_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/search_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/deploy_keys_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/tree_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/commit_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/refs_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/controllers/application_controller.rb Wed, 24 Oct 2012 14:17:22 +0300
+app/controllers/notes_controller.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/uploaders/attachment_uploader.rb Wed, 22 Aug 2012 14:52:27 +0300
+app/models/tree.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/project.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/issue.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/project_hook.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/group.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/key.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/snippet.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/user.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/note.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/wiki.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/users_project.rb Wed, 24 Oct 2012 16:14:03 +0300
+app/models/web_hook.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/ability.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/milestone.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/commit.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/protected_branch.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/merge_request.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/event.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/models/system_hook.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/decorators/commit_decorator.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/decorators/event_decorator.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/decorators/application_decorator.rb Fri, 21 Sep 2012 15:40:04 +0300
+app/decorators/tree_decorator.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/tags_helper.rb Wed, 06 Jun 2012 13:56:49 +0300
+app/helpers/application_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/gitlab_markdown_helper.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/helpers/notes_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/profile_helper.rb Fri, 21 Sep 2012 15:47:07 +0300
+app/helpers/tree_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/commits_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/projects_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/events_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/issues_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/tab_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+app/helpers/snippets_helper.rb Wed, 06 Jun 2012 13:56:49 +0300
+app/helpers/merge_requests_helper.rb Mon, 22 Oct 2012 16:08:18 +0300
+lib/file_size_validator.rb Wed, 22 Aug 2012 14:52:27 +0300
+lib/api.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/gitlab/encode.rb Wed, 22 Aug 2012 14:52:27 +0300
+lib/gitlab/graph_commit.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/gitlab/theme.rb Tue, 26 Jun 2012 16:08:37 +0300
+lib/gitlab/app_logger.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/gitlab/inline_diff.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/merge.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/backend/gitolite.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/gitlab/backend/grack_auth.rb Mon, 22 Oct 2012 19:02:02 +0300
+lib/gitlab/backend/gitolite_config.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/git_logger.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/gitlab/markdown.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/file_editor.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/logger.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/satellite.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/gitlab/auth.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/extracts_path.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/api/issues.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/api/projects.rb Mon, 22 Oct 2012 16:08:18 +0300
+lib/api/helpers.rb Mon, 22 Oct 2012 16:08:18 +0300
+lib/api/entities.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/api/session.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/api/users.rb Mon, 22 Oct 2012 16:08:19 +0300
+lib/api/milestones.rb Fri, 21 Sep 2012 15:47:07 +0300
+lib/redcarpet/render/gitlab_html.rb Wed, 22 Aug 2012 14:52:27 +0300
diff --git a/doc/app/doc/README_FOR_APP.html b/doc/app/doc/README_FOR_APP.html
new file mode 100644
index 00000000..9456512e
--- /dev/null
+++ b/doc/app/doc/README_FOR_APP.html
@@ -0,0 +1,399 @@
+
+
+
+
+
+
+README_FOR_APP - Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use this README file to introduce your application and point to useful
+places in the API for learning more. Run “rake doc:app” to generate API
+documentation for your models, controllers, helpers, and libraries.
+
+
+
+
+
+
+
diff --git a/doc/app/images/add.png b/doc/app/images/add.png
new file mode 100755
index 00000000..6332fefe
Binary files /dev/null and b/doc/app/images/add.png differ
diff --git a/doc/app/images/brick.png b/doc/app/images/brick.png
new file mode 100644
index 00000000..7851cf34
Binary files /dev/null and b/doc/app/images/brick.png differ
diff --git a/doc/app/images/brick_link.png b/doc/app/images/brick_link.png
new file mode 100644
index 00000000..9ebf013a
Binary files /dev/null and b/doc/app/images/brick_link.png differ
diff --git a/doc/app/images/bug.png b/doc/app/images/bug.png
new file mode 100644
index 00000000..2d5fb90e
Binary files /dev/null and b/doc/app/images/bug.png differ
diff --git a/doc/app/images/bullet_black.png b/doc/app/images/bullet_black.png
new file mode 100644
index 00000000..57619706
Binary files /dev/null and b/doc/app/images/bullet_black.png differ
diff --git a/doc/app/images/bullet_toggle_minus.png b/doc/app/images/bullet_toggle_minus.png
new file mode 100644
index 00000000..b47ce55f
Binary files /dev/null and b/doc/app/images/bullet_toggle_minus.png differ
diff --git a/doc/app/images/bullet_toggle_plus.png b/doc/app/images/bullet_toggle_plus.png
new file mode 100644
index 00000000..9ab4a896
Binary files /dev/null and b/doc/app/images/bullet_toggle_plus.png differ
diff --git a/doc/app/images/date.png b/doc/app/images/date.png
new file mode 100644
index 00000000..783c8335
Binary files /dev/null and b/doc/app/images/date.png differ
diff --git a/doc/app/images/delete.png b/doc/app/images/delete.png
new file mode 100755
index 00000000..08f24936
Binary files /dev/null and b/doc/app/images/delete.png differ
diff --git a/doc/app/images/find.png b/doc/app/images/find.png
new file mode 100644
index 00000000..15474796
Binary files /dev/null and b/doc/app/images/find.png differ
diff --git a/doc/app/images/loadingAnimation.gif b/doc/app/images/loadingAnimation.gif
new file mode 100644
index 00000000..82290f48
Binary files /dev/null and b/doc/app/images/loadingAnimation.gif differ
diff --git a/doc/app/images/macFFBgHack.png b/doc/app/images/macFFBgHack.png
new file mode 100644
index 00000000..c6473b32
Binary files /dev/null and b/doc/app/images/macFFBgHack.png differ
diff --git a/doc/app/images/package.png b/doc/app/images/package.png
new file mode 100644
index 00000000..da3c2a2d
Binary files /dev/null and b/doc/app/images/package.png differ
diff --git a/doc/app/images/page_green.png b/doc/app/images/page_green.png
new file mode 100644
index 00000000..de8e003f
Binary files /dev/null and b/doc/app/images/page_green.png differ
diff --git a/doc/app/images/page_white_text.png b/doc/app/images/page_white_text.png
new file mode 100644
index 00000000..813f712f
Binary files /dev/null and b/doc/app/images/page_white_text.png differ
diff --git a/doc/app/images/page_white_width.png b/doc/app/images/page_white_width.png
new file mode 100644
index 00000000..1eb88094
Binary files /dev/null and b/doc/app/images/page_white_width.png differ
diff --git a/doc/app/images/plugin.png b/doc/app/images/plugin.png
new file mode 100644
index 00000000..6187b15a
Binary files /dev/null and b/doc/app/images/plugin.png differ
diff --git a/doc/app/images/ruby.png b/doc/app/images/ruby.png
new file mode 100644
index 00000000..f763a168
Binary files /dev/null and b/doc/app/images/ruby.png differ
diff --git a/doc/app/images/tag_blue.png b/doc/app/images/tag_blue.png
new file mode 100755
index 00000000..3f02b5f8
Binary files /dev/null and b/doc/app/images/tag_blue.png differ
diff --git a/doc/app/images/tag_green.png b/doc/app/images/tag_green.png
new file mode 100644
index 00000000..83ec984b
Binary files /dev/null and b/doc/app/images/tag_green.png differ
diff --git a/doc/app/images/transparent.png b/doc/app/images/transparent.png
new file mode 100644
index 00000000..d665e179
Binary files /dev/null and b/doc/app/images/transparent.png differ
diff --git a/doc/app/images/wrench.png b/doc/app/images/wrench.png
new file mode 100644
index 00000000..5c8213fe
Binary files /dev/null and b/doc/app/images/wrench.png differ
diff --git a/doc/app/images/wrench_orange.png b/doc/app/images/wrench_orange.png
new file mode 100644
index 00000000..565a9330
Binary files /dev/null and b/doc/app/images/wrench_orange.png differ
diff --git a/doc/app/images/zoom.png b/doc/app/images/zoom.png
new file mode 100644
index 00000000..908612e3
Binary files /dev/null and b/doc/app/images/zoom.png differ
diff --git a/doc/app/index.html b/doc/app/index.html
new file mode 100644
index 00000000..a46b4fbc
--- /dev/null
+++ b/doc/app/index.html
@@ -0,0 +1,392 @@
+
+
+
+
+
+
+Rails Application Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+This is the API documentation for Rails Application Documentation.
+
+
+
+
diff --git a/doc/app/js/darkfish.js b/doc/app/js/darkfish.js
new file mode 100644
index 00000000..4be722fa
--- /dev/null
+++ b/doc/app/js/darkfish.js
@@ -0,0 +1,153 @@
+/**
+ *
+ * Darkfish Page Functions
+ * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $
+ *
+ * Author: Michael Granger
+ *
+ */
+
+/* Provide console simulation for firebug-less environments */
+if (!("console" in window) || !("firebug" in console)) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+ "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+
+ window.console = {};
+ for (var i = 0; i < names.length; ++i)
+ window.console[names[i]] = function() {};
+};
+
+
+/**
+ * Unwrap the first element that matches the given @expr@ from the targets and return them.
+ */
+$.fn.unwrap = function( expr ) {
+ return this.each( function() {
+ $(this).parents( expr ).eq( 0 ).after( this ).remove();
+ });
+};
+
+
+function showSource( e ) {
+ var target = e.target;
+ var codeSections = $(target).
+ parents('.method-detail').
+ find('.method-source-code');
+
+ $(target).
+ parents('.method-detail').
+ find('.method-source-code').
+ slideToggle();
+};
+
+function hookSourceViews() {
+ $('.method-heading').click( showSource );
+};
+
+function toggleDebuggingSection() {
+ $('.debugging-section').slideToggle();
+};
+
+function hookDebuggingToggle() {
+ $('#debugging-toggle img').click( toggleDebuggingSection );
+};
+
+function hookTableOfContentsToggle() {
+ $('.indexpage li .toc-toggle').each( function() {
+ $(this).click( function() {
+ $(this).toggleClass('open');
+ });
+
+ var section = $(this).next();
+
+ $(this).click( function() {
+ section.slideToggle();
+ });
+ });
+}
+
+function hookSearch() {
+ var input = $('#search-field').eq(0);
+ var result = $('#search-results').eq(0);
+ $(result).show();
+
+ var search_section = $('#search-section').get(0);
+ $(search_section).show();
+
+ var search = new Search(search_data, input, result);
+
+ search.renderItem = function(result) {
+ var li = document.createElement('li');
+ var html = '';
+
+ // TODO add relative path to
+
+
+
+
+
+
+
+
+
+
+Table of Contents - Rails Application Documentation
+
+Pages
+
+
+Classes/Modules
+
+
+Methods
+
+
+
+
+
diff --git a/doc/development.md b/doc/development.md
index 67bcb8e1..179c708d 100644
--- a/doc/development.md
+++ b/doc/development.md
@@ -1,45 +1,36 @@
-## Development tips:
+## Development tips:
+
+
+### Installation
+
+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.
+
### Start application in development mode
-#### 1. Via foreman
+#### 1. Via foreman
- bundle exec foreman -p 3000
+ bundle exec foreman start -p 3000
-#### 2. Via gitlab cli
+#### 2. Manually
- ./gitlab start
-
-#### 3. Manually
-
- bundle exec rails s
- bundle exec rake environment resque:work QUEUE=* VVERBOSE=1
+ bundle exec rails s
+ bundle exec rake environment resque:work QUEUE=* VVERBOSE=1
-### Run tests:
-
-#### 1. Packages
-
- # ubuntu
- sudo apt-get install libqt4-dev libqtwebkit-dev
- sudo apt-get install xvfb
-
- # Mac
- brew install qt
- brew install xvfb
-
-#### 2. DB & seeds
+### Test DB seutup & seed
bundle exec rake db:setup RAILS_ENV=test
bundle exec rake db:seed_fu RAILS_ENV=test
-### 3. Run Tests
+
+### Run the Tests
# All in one
bundle exec rake gitlab:test
-
- # Rspec
+
+ # Rspec
bundle exec rake spec
-
+
# Spinach
bundle exec rake spinach
diff --git a/doc/install/databases.md b/doc/install/databases.md
new file mode 100644
index 00000000..b7beff26
--- /dev/null
+++ b/doc/install/databases.md
@@ -0,0 +1,71 @@
+# Databases:
+
+GitLab use mysql as default database but you are free to use PostgreSQL or SQLite.
+
+
+## SQLite
+
+ sudo apt-get install -y sqlite3 libsqlite3-dev
+
+## MySQL
+
+ sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
+
+ # Login to MySQL
+ $ mysql -u root -p
+
+ # Create the GitLab production database
+ mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
+
+ # Create the MySQL User change $password to a real password
+ mysql> CREATE USER 'gitlab'@'localhost' IDENTIFIED BY '$password';
+
+ # Grant proper permissions to the MySQL User
+ mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
+
+
+## PostgreSQL
+
+ sudo apt-get install -y postgresql-9.1 postgresql-server-dev-9.1
+
+ # Connect to database server
+ sudo -u postgres psql -d template1
+
+ # Add a user called gitlab. Change $password to a real password
+ template1=# CREATE USER gitlab WITH PASSWORD '$password';
+
+ # Create the GitLab production database & grant all privileges on database
+ template1=# CREATE DATABASE gitlabhq_production OWNER gitlab;
+
+ # Quit from PostgreSQL server
+ template1=# \q
+
+ # Try connect to new database
+ sudo -u gitlab psql -d gitlabhq_production
+
+
+
+#### Select the database you want to use
+
+ # SQLite
+ sudo -u gitlab cp config/database.yml.sqlite config/database.yml
+
+ # Mysql
+ sudo -u gitlab cp config/database.yml.mysql config/database.yml
+
+ # PostgreSQL
+ sudo -u gitlab cp config/database.yml.postgresql config/database.yml
+
+ # make sure to update username/password in config/database.yml
+
+#### Install gems
+
+ # mysql
+ sudo -u gitlab -H bundle install --without development test sqlite postgres --deployment
+
+ # or postgres
+ sudo -u gitlab -H bundle install --without development test sqlite mysql --deployment
+
+ # or sqlite
+ sudo -u gitlab -H bundle install --without development test mysql postgres --deployment
+
diff --git a/doc/installation.md b/doc/install/installation.md
similarity index 61%
rename from doc/installation.md
rename to doc/install/installation.md
index b1b954f1..07ed0b0f 100644
--- a/doc/installation.md
+++ b/doc/install/installation.md
@@ -1,43 +1,7 @@
-## Platform requirements:
+_This installation guide created for Debian/Ubuntu and properly tested._
-**The project is designed for the Linux operating system.**
+_Checkout requirements before setup_
-It may work on FreeBSD and Mac OS, but we don't test our application for these systems and can't guarantee stability and full functionality.
-
-We officially support (recent versions of) these Linux distributions:
-
-- Ubuntu Linux
-- Debian/GNU Linux
-
-It should work on:
-
-- Fedora
-- CentOs
-- RedHat
-
-You might have some luck using these, but no guarantees:
-
- - MacOS X
- - FreeBSD
-
-GitLab does **not** run on Windows and we have no plans of making GitLab compatible.
-
-
-## Hardware:
-
-We recommend to use server with at least 1GB RAM for gitlab instance.
-
-
-## This installation guide created for Debian/Ubuntu and properly tested.
-
-The installation consists of 6 steps:
-
-1. Install packages / dependencies
-2. Install ruby
-3. Install Gitolite
-4. Install and configure GitLab.
-5. Start the web front-end
-6. Start a Resque worker (for background processing)
### IMPORTANT
@@ -47,25 +11,29 @@ Only create a GitHub Issue if you want a specific part of this installation guid
Also read the [Read this before you submit an issue](https://github.com/gitlabhq/gitlabhq/wiki/Read-this-before-you-submit-an-issue) wiki page.
-> - - -
-> The first 3 steps of this guide can be easily skipped by executing an install script:
->
-> # Install curl and sudo
-> apt-get install curl sudo
->
-> # 3 steps in 1 command :)
-> curl https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu.sh | sh
->
-> Now you can go to [Step 4](#4-install-gitlab-and-configuration-check-status-configuration)
->
-> Or if you are installing on Amazon Web Services using Ubuntu 12.04 you can do all steps (1 to 6) at once with:
->
-> curl https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu_aws.sh | sh
->
-> for more detailed instructions read the HOWTO section of [the script](https://github.com/gitlabhq/gitlab-recipes/blob/master/install/debian_ubuntu_aws.sh)
-> - - -
+- - -
-# 1. Install packages
+# Basic setup
+
+The basic installation will provide you a GitLab setup with options:
+
+1. ruby 1.9.3
+2. mysql as main db
+3. gitolite v3 fork by gitlab
+4. nginx + unicorn
+
+The installation consists of next steps:
+
+1. Packages / dependencies
+2. Ruby
+3. Users
+4. Gitolite
+5. Mysql
+6. GitLab.
+7. Nginx
+
+
+# 1. Packages / dependencies
*Keep in mind that `sudo` is not installed on Debian by default. You should install it as root:*
@@ -78,52 +46,7 @@ Now install the required packages:
sudo apt-get install -y wget curl gcc checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libreadline6-dev libc6-dev libssl-dev libmysql++-dev make build-essential zlib1g-dev libicu-dev redis-server openssh-server git-core python-dev python-pip libyaml-dev postfix libpq-dev
-
-# Database
-
-## SQLite
-
- sudo apt-get install -y sqlite3 libsqlite3-dev
-
-## MySQL
-
- sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
-
- # Login to MySQL
- $ mysql -u root -p
-
- # Create the GitLab production database
- mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
-
- # Create the MySQL User change $password to a real password
- mysql> CREATE USER 'gitlab'@'localhost' IDENTIFIED BY '$password';
-
- # Grant proper permissions to the MySQL User
- mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
-
-
-## PostgreSQL
-
- sudo apt-get install -y postgresql-9.2 postgresql-server-dev-9.2
-
- # Connect to database server
- sudo -u postgres psql -d template1
-
- # Add a user called gitlab. Change $password to a real password
- template1=# CREATE USER gitlab WITH PASSWORD '$password';
-
- # Create the GitLab production database
- template1=# CREATE DATABASE IF NOT EXISTS gitlabhq_production;
-
- # Grant all privileges on database
- template1=# GRANT ALL PRIVILEGES ON DATABASE gitlabhq_production to gitlab;
-
- # Quit from PostgreSQL server
- template1=# \q
-
- # Try connect to new database
- $ su - gitlab
- $ psql -d gitlabhq_production -U gitlab
+ sudo pip install pygments
# 2. Install Ruby
@@ -135,7 +58,7 @@ Now install the required packages:
make
sudo make install
-# 3. Install Gitolite
+# 3. Users
Create user for git:
@@ -153,18 +76,18 @@ Create user for GitLab:
# ubuntu/debian
sudo adduser --disabled-login --gecos 'gitlab system' gitlab
-Add your user to the `git` group:
+Add your users to groups:
sudo usermod -a -G git gitlab
-
-Add `git` user to `gitlab` group:
-
sudo usermod -a -G gitlab git
Generate key:
sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
+
+# 4. Gitolite
+
Clone GitLab's fork of the Gitolite source code:
sudo -H -u git git clone -b gl-v304 https://github.com/gitlabhq/gitolite.git /home/git/gitolite
@@ -180,16 +103,13 @@ Setup:
sudo chmod 0444 /home/git/gitlab.pub
sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
- sudo -u git -H sed -i 's/0077/0007/g' /home/git/.gitolite.rc
- sudo -u git -H sed -i "s/\(GIT_CONFIG_KEYS\s*=>*\s*\).\{2\}/\1'\.\*'/g" /home/git/.gitolite.rc
+
Permissions:
sudo chmod -R g+rwX /home/git/repositories/
sudo chown -R git:git /home/git/repositories/
-#### CHECK: Logout & login again to apply git group to your user
-
# clone admin repo to add localhost to known_hosts
# & be sure your user has access to gitolite
sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
@@ -201,13 +121,31 @@ Permissions:
Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
and ensure you have followed all of the above steps carefully.
-# 4. Clone GitLab source and install prerequisites
- sudo gem install charlock_holmes --version '0.6.8'
- sudo pip install pygments
- sudo gem install bundler
+# 5. Mysql database
+
+ sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
+
+ # Login to MySQL
+ $ mysql -u root -p
+
+ # Create the GitLab production database
+ mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
+
+ # Create the MySQL User change $password to a real password
+ mysql> CREATE USER 'gitlab'@'localhost' IDENTIFIED BY '$password';
+
+ # Grant proper permissions to the MySQL User
+ mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlabhq_production`.* TO 'gitlab'@'localhost';
+
+
+# 6. GitLab
+
cd /home/gitlab
+
+#### Get source code
+
# Get gitlab code. Use this for stable setup
sudo -H -u gitlab git clone -b stable https://github.com/gitlabhq/gitlabhq.git gitlab
@@ -215,35 +153,33 @@ and ensure you have followed all of the above steps carefully.
# Master branch (recent changes, less stable)
sudo -H -u gitlab git clone -b master https://github.com/gitlabhq/gitlabhq.git gitlab
+
+#### Copy configs
+
cd gitlab
# Rename config files
+ #
sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml
-#### Select the database you want to use
-
- # SQLite
- sudo -u gitlab cp config/database.yml.sqlite config/database.yml
-
- # Mysql
+ # Copy mysql db config
+ #
+ # make sure to update username/password in config/database.yml
+ #
sudo -u gitlab cp config/database.yml.mysql config/database.yml
- # PostgreSQL
- sudo -u gitlab cp config/database.yml.postgres config/database.yml
-
- # make sure to update username/password in config/database.yml
+ # Copy unicorn config
+ #
+ sudo -u gitlab cp config/unicorn.rb.example config/unicorn.rb
#### Install gems
- # mysql
+ cd /home/gitlab/gitlab
+
+ sudo gem install charlock_holmes --version '0.6.9'
+ sudo gem install bundler
sudo -u gitlab -H bundle install --without development test sqlite postgres --deployment
- # or postgres
- sudo -u gitlab -H bundle install --without development test sqlite mysql --deployment
-
- # or sqlite
- sudo -u gitlab -H bundle install --without development test mysql postgres --deployment
-
#### Configure git client
Gitlab needs to be able to commit and push changes to gitolite.
@@ -252,10 +188,11 @@ Git requires a username and email in order to be able to do that.
sudo -u gitlab -H git config --global user.email "gitlab@localhost"
sudo -u gitlab -H git config --global user.name "Gitlab"
-#### Setup database
+#### Setup application
sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
+
#### Setup GitLab hooks
sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
@@ -283,53 +220,25 @@ Checking status:
UMASK for .gitolite.rc is 0007? ............YES
/home/git/share/gitolite/hooks/common/post-receive exists? ............YES
-If you got all YES - congratulations! You can go to the next step.
+If you got all YES - congratulations! You can run a GitLab app.
-# 5. Start the web server
+#### init script
-Application can be started with next command:
+Create init script in /etc/init.d/gitlab:
- # For test purposes
- sudo -u gitlab bundle exec rails s -e production
+ sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab -P /etc/init.d/
+ sudo chmod +x /etc/init.d/gitlab
- # As daemon
- sudo -u gitlab bundle exec rails s -e production -d
+GitLab autostart:
-You can login via web using admin generated with setup:
+ sudo update-rc.d gitlab defaults 21
- admin@local.host
- 5iveL!fe
+#### Now you should start GitLab application:
-# 6. Run Resque process (for processing job queue).
+ sudo service gitlab start
- # Manually
- sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes
- # GitLab start script
- sudo -u gitlab ./resque.sh
- # if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root
- # causing the resque worker not to start via init script on next boot/service restart
-
-## Customizing Resque's Redis connection
-
-If you'd like Resque to connect to a Redis server on a non-standard port or on
-a different host, you can configure its connection string in the
-**config/resque.yml** file:
-
- production: redis.example.com:6379
-
-**Ok - we have a working application now. **
-**But keep going - there are some things that should be done **
-
-# Nginx && Unicorn
-
-## 1. Unicorn
-
- cd /home/gitlab/gitlab
- sudo -u gitlab cp config/unicorn.rb.example config/unicorn.rb
- sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
-
-## 2. Nginx
+# 7. Nginx
# Install first
sudo apt-get install nginx
@@ -346,17 +255,29 @@ a different host, you can configure its connection string in the
# Restart nginx:
sudo /etc/init.d/nginx restart
-## 3. Init script
-Create init script in /etc/init.d/gitlab:
+# Done! Visit YOUR_SERVER for gitlab instance
- sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab -P /etc/init.d/
- sudo chmod +x /etc/init.d/gitlab
+You can login via web using admin generated with setup:
-GitLab autostart:
+ admin@local.host
+ 5iveL!fe
- sudo update-rc.d gitlab defaults 21
-Now you can start/restart/stop GitLab like:
+- - -
- sudo /etc/init.d/gitlab restart
+
+# Advanced setup tips:
+
+_Checkout databases.md for postgres or sqlite_
+
+## Customizing Resque's Redis connection
+
+If you'd like Resque to connect to a Redis server on a non-standard port or on
+a different host, you can configure its connection string in the
+**config/resque.yml** file:
+
+ production: redis.example.com:6379
+
+**Ok - we have a working application now. **
+**But keep going - there are some things that should be done **
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
new file mode 100644
index 00000000..75b02d64
--- /dev/null
+++ b/doc/install/requirements.md
@@ -0,0 +1,28 @@
+## Platform requirements:
+
+**The project is designed for the Linux operating system.**
+
+It may work on FreeBSD and Mac OS, but we don't test our application for these systems and can't guarantee stability and full functionality.
+
+We officially support (recent versions of) these Linux distributions:
+
+- Ubuntu Linux
+- Debian/GNU Linux
+
+It should work on:
+
+- Fedora
+- CentOs
+- RedHat
+
+You might have some luck using these, but no guarantees:
+
+- FreeBSD will likely work, see https://github.com/gitlabhq/gitlabhq/issues/796
+- MacOS X will likely work, see https://groups.google.com/forum/#!topic/gitlabhq/5IXHbPkjKLA
+
+GitLab does **not** run on Windows and we have no plans of making GitLab compatible.
+
+
+## Hardware:
+
+We recommend to use server with at least 1GB RAM for gitlab instance.
diff --git a/features/dashboard/search.feature b/features/dashboard/search.feature
index 91d870f4..9813d9d1 100644
--- a/features/dashboard/search.feature
+++ b/features/dashboard/search.feature
@@ -2,8 +2,13 @@ Feature: Dashboard Search
Background:
Given I sign in as a user
And I own project "Shop"
+ And Project "Shop" has wiki page "Contibuting guide"
And I visit dashboard search page
Scenario: I should see project I am looking for
Given I search for "Sho"
Then I should see "Shop" project link
+
+ Scenario: I should see wiki page I am looking for
+ Given I search for "Contibuting"
+ Then I should see "Contibuting guide" wiki link
\ No newline at end of file
diff --git a/features/profile/profile.feature b/features/profile/profile.feature
index d07a6db1..a98988b8 100644
--- a/features/profile/profile.feature
+++ b/features/profile/profile.feature
@@ -16,6 +16,11 @@ Feature: Profile
Then I change my password
And I should be redirected to sign in page
+ Scenario: I unsuccessfully change my password
+ Given I visit profile account page
+ When I unsuccessfully change my password
+ Then I should see a password error message
+
Scenario: I reset my token
Given I visit profile account page
Then I reset my token
diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature
index df795ef7..56069cdc 100644
--- a/features/project/commits/commits.feature
+++ b/features/project/commits/commits.feature
@@ -19,3 +19,11 @@ Feature: Project Browse commits
Given I visit compare refs page
And I fill compare fields with refs
Then I see compared refs
+
+ Scenario: I browse commits for a specific path
+ Given I visit my project's commits page for a specific path
+ Then I see breadcrumb links
+
+ Scenario: I browse commits stats
+ Given I visit my project's commits stats page
+ Then I see commits stats
diff --git a/features/steps/dashboard/dashboard.rb b/features/steps/dashboard/dashboard.rb
index b22b2465..008c1451 100644
--- a/features/steps/dashboard/dashboard.rb
+++ b/features/steps/dashboard/dashboard.rb
@@ -32,7 +32,7 @@ class Dashboard < Spinach::FeatureSteps
end
Given 'user with name "John Doe" joined project "Shop"' do
- user = Factory.create(:user, {name: "John Doe"})
+ user = create :user, {name: "John Doe"}
project = Project.find_by_name "Shop"
Event.create(
project: project,
@@ -60,14 +60,14 @@ class Dashboard < Spinach::FeatureSteps
end
And 'I own project "Shop"' do
- @project = Factory :project, :name => 'Shop'
+ @project = create :project, name: 'Shop'
@project.add_access(@user, :admin)
end
And 'I have group with projects' do
- @group = Factory :group
- @project = Factory :project, group: @group
- @event = Factory :closed_issue_event, project: @project
+ @group = create :group
+ @project = create :project, group: @group
+ @event = create :closed_issue_event, project: @project
@project.add_access current_user, :admin
end
@@ -76,25 +76,25 @@ class Dashboard < Spinach::FeatureSteps
@project = Project.find_by_name("Shop")
data = {
- :before => "0000000000000000000000000000000000000000",
- :after => "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
- :ref => "refs/heads/new_design",
- :user_id => @user.id,
- :user_name => @user.name,
- :repository => {
- :name => @project.name,
- :url => "localhost/rubinius",
- :description => "",
- :homepage => "localhost/rubinius",
- :private => true
+ before: "0000000000000000000000000000000000000000",
+ after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
+ ref: "refs/heads/new_design",
+ user_id: @user.id,
+ user_name: @user.name,
+ repository: {
+ name: @project.name,
+ url: "localhost/rubinius",
+ description: "",
+ homepage: "localhost/rubinius",
+ private: true
}
}
@event = Event.create(
- :project => @project,
- :action => Event::Pushed,
- :data => data,
- :author_id => @user.id
+ project: @project,
+ action: Event::Pushed,
+ data: data,
+ author_id: @user.id
)
end
diff --git a/features/steps/dashboard/dashboard_issues.rb b/features/steps/dashboard/dashboard_issues.rb
index 9368782b..e5caf905 100644
--- a/features/steps/dashboard/dashboard_issues.rb
+++ b/features/steps/dashboard/dashboard_issues.rb
@@ -11,9 +11,9 @@ class DashboardIssues < Spinach::FeatureSteps
end
And 'I have assigned issues' do
- project = Factory :project
+ project = create :project
project.add_access(@user, :read, :write)
- 2.times { Factory :issue, :author => @user, :assignee => @user, :project => project }
+ 2.times { create :issue, author: @user, assignee: @user, project: project }
end
end
diff --git a/features/steps/dashboard/dashboard_merge_requests.rb b/features/steps/dashboard/dashboard_merge_requests.rb
index fc339e75..485a4ccc 100644
--- a/features/steps/dashboard/dashboard_merge_requests.rb
+++ b/features/steps/dashboard/dashboard_merge_requests.rb
@@ -11,13 +11,13 @@ class DashboardMergeRequests < Spinach::FeatureSteps
end
And 'I have authored merge requests' do
- project1 = Factory :project
- project2 = Factory :project
+ project1 = create :project
+ project2 = create :project
project1.add_access(@user, :read, :write)
project2.add_access(@user, :read, :write)
- merge_request1 = Factory :merge_request, :author => @user, :project => project1
- merge_request2 = Factory :merge_request, :author => @user, :project => project2
+ merge_request1 = create :merge_request, author: @user, project: project1
+ merge_request2 = create :merge_request, author: @user, project: project2
end
end
diff --git a/features/steps/dashboard/dashboard_search.rb b/features/steps/dashboard/dashboard_search.rb
index e3585898..53d74bf3 100644
--- a/features/steps/dashboard/dashboard_search.rb
+++ b/features/steps/dashboard/dashboard_search.rb
@@ -3,7 +3,7 @@ class DashboardSearch < Spinach::FeatureSteps
include SharedPaths
Given 'I search for "Sho"' do
- fill_in "dashboard_search", :with => "Sho"
+ fill_in "dashboard_search", with: "Sho"
click_button "Search"
end
@@ -12,7 +12,23 @@ class DashboardSearch < Spinach::FeatureSteps
end
And 'I own project "Shop"' do
- @project = Factory :project, :name => "Shop"
+ @project = create :project, name: "Shop"
@project.add_access(@user, :admin)
end
+
+ Given 'I search for "Contibuting"' do
+ fill_in "dashboard_search", with: "Contibuting"
+ click_button "Search"
+ end
+
+ And 'Project "Shop" has wiki page "Contibuting guide"' do
+ @wiki_page = create :wiki,
+ project: @project,
+ title: "Contibuting guide",
+ slug: "contributing"
+ end
+
+ Then 'I should see "Contibuting guide" wiki link' do
+ page.should have_link "Contibuting guide"
+ end
end
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 605936ba..efab1010 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -28,6 +28,16 @@ class Profile < Spinach::FeatureSteps
click_button "Save"
end
+ When 'I unsuccessfully change my password' do
+ fill_in "user_password", with: "password"
+ fill_in "user_password_confirmation", with: "confirmation"
+ click_button "Save"
+ end
+
+ Then "I should see a password error message" do
+ page.should have_content "Password doesn't match confirmation"
+ end
+
And 'I should be redirected to sign in page' do
current_path.should == new_user_session_path
end
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index cb5cabe9..428c14a8 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -42,4 +42,19 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
page.should have_content "Commits (1)"
page.should have_content "Showing 2 changed files"
end
+
+ Then 'I see breadcrumb links' do
+ page.should have_selector('ul.breadcrumb')
+ page.should have_selector('ul.breadcrumb span.divider', count: 3)
+ page.should have_selector('ul.breadcrumb a', count: 4)
+
+ find('ul.breadcrumb li:first a')['href'].should match(/#{@project.path}\/commits\/master\z/)
+ find('ul.breadcrumb li:last a')['href'].should match(%r{master/app/models/project\.rb\z})
+ end
+
+ Then 'I see commits stats' do
+ page.should have_content 'Stats for master'
+ page.should have_content 'Committers'
+ page.should have_content 'Total commits'
+ end
end
diff --git a/features/steps/project/project_network_graph.rb b/features/steps/project/project_network_graph.rb
index f34a81a4..6fde532f 100644
--- a/features/steps/project/project_network_graph.rb
+++ b/features/steps/project/project_network_graph.rb
@@ -11,12 +11,10 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
end
And 'I visit project "Shop" network page' do
+ # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
+ Gitlab::Graph::JsonBuilder.stub(max_count: 10)
+
project = Project.find_by_name("Shop")
-
- # Stub out find_all to speed this up (10 commits vs. 650)
- commits = Grit::Commit.find_all(project.repo, nil, {max_count: 10})
- Grit::Commit.stub(:find_all).and_return(commits)
-
visit graph_project_path(project)
end
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index b4e4b810..33a94027 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -121,10 +121,17 @@ module SharedPaths
visit project_commits_path(@project, @project.root_ref, {limit: 5})
end
+ Given "I visit my project's commits page for a specific path" do
+ visit project_commits_path(@project, @project.root_ref + "/app/models/project.rb", {limit: 5})
+ end
+
+ Given 'I visit my project\'s commits stats page' do
+ visit stats_project_repository_path(@project)
+ end
+
Given "I visit my project's network page" do
- # Stub out find_all to speed this up (10 commits vs. 650)
- commits = Grit::Commit.find_all(@project.repo, nil, {max_count: 10})
- Grit::Commit.stub(:find_all).and_return(commits)
+ # Stub Graph::JsonBuilder max_size to speed up test (10 commits vs. 650)
+ Gitlab::Graph::JsonBuilder.stub(max_count: 10)
visit graph_project_path(@project)
end
diff --git a/gitlab b/gitlab
deleted file mode 100755
index acafb3f1..00000000
--- a/gitlab
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env ruby
-
-class GitlabCli
- def initialize
- @path = File.dirname(__FILE__)
- @command = ARGV.shift
- @mode = ARGV.shift
- end
-
- def execute
- case @command
- when 'start' then start
- when 'stop' then stop
- else
- puts "-- Usage gitlab start production or gitlab stop development"
- end
- end
-
- private
-
- def start
- case @mode
- when 'production';
- system(unicorn_start_cmd)
- system(resque_start_cmd)
- else
- system(rails_start_cmd)
- system(resque_dev_start_cmd)
- end
- end
-
- def stop
- case @mode
- when 'production';
- system(unicorn_stop_cmd)
- else
- system(rails_stop_cmd)
- end
- system(resque_stop_cmd)
- end
-
- def rails_start_cmd
- "bundle exec rails s -d"
- end
-
- def rails_stop_cmd
- pid = File.join(@path, "tmp/pids/server.pid")
- "kill -QUIT `cat #{pid}`"
- end
-
- def unicorn_start_cmd
- unicorn_conf = File.join(@path, "config/unicorn.rb")
- "bundle exec unicorn_rails -c #{unicorn_conf} -E production -D"
- end
-
- def unicorn_stop_cmd
- pid = File.join(@path, "/tmp/pids/unicorn.pid")
- "kill -QUIT `cat #{pid}`"
- end
-
- def resque_dev_start_cmd
- "./resque_dev.sh > /dev/null 2>&1"
- end
-
- def resque_start_cmd
- "./resque.sh > /dev/null 2>&1"
- end
-
- def resque_stop_cmd
- pid = File.join(@path, "tmp/pids/resque_worker.pid")
- "kill -QUIT `cat #{pid}`"
- end
-end
-
-GitlabCli.new.execute
diff --git a/lib/api.rb b/lib/api.rb
index 2890a8cc..7a184544 100644
--- a/lib/api.rb
+++ b/lib/api.rb
@@ -18,5 +18,6 @@ module Gitlab
mount Issues
mount Milestones
mount Session
+ mount MergeRequests
end
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index ee693de6..9e605a60 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -63,5 +63,15 @@ module Gitlab
class SSHKey < Grape::Entity
expose :id, :title, :key
end
+
+ class MergeRequest < Grape::Entity
+ expose :id, :target_branch, :source_branch, :project_id, :title, :closed, :merged
+ expose :author, :assignee, using: Entities::UserBasic
+ end
+
+ class Note < Grape::Entity
+ expose :author, using: Entities::UserBasic
+ expose :note
+ end
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
new file mode 100644
index 00000000..d8f2c512
--- /dev/null
+++ b/lib/api/merge_requests.rb
@@ -0,0 +1,118 @@
+module Gitlab
+ # MergeRequest API
+ class MergeRequests < Grape::API
+ before { authenticate! }
+
+ resource :projects do
+
+ # List merge requests
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ #
+ # Example:
+ # GET /projects/:id/merge_requests
+ #
+ get ":id/merge_requests" do
+ authorize! :read_merge_request, user_project
+
+ present paginate(user_project.merge_requests), with: Entities::MergeRequest
+ end
+
+ # Show MR
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # merge_request_id (required) - The ID of MR
+ #
+ # Example:
+ # GET /projects/:id/merge_request/:merge_request_id
+ #
+ get ":id/merge_request/:merge_request_id" do
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+
+ authorize! :read_merge_request, merge_request
+
+ present merge_request, with: Entities::MergeRequest
+ end
+
+ # Create MR
+ #
+ # Parameters:
+ #
+ # id (required) - The ID or code name of a project
+ # source_branch (required) - The source branch
+ # target_branch (required) - The target branch
+ # assignee_id - Assignee user ID
+ # title (required) - Title of MR
+ #
+ # Example:
+ # POST /projects/:id/merge_requests
+ #
+ post ":id/merge_requests" do
+ authorize! :write_merge_request, user_project
+
+ attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title]
+ merge_request = user_project.merge_requests.new(attrs)
+ merge_request.author = current_user
+
+ if merge_request.save
+ merge_request.reload_code
+ present merge_request, with: Entities::MergeRequest
+ else
+ not_found!
+ end
+ end
+
+ # Update MR
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # merge_request_id (required) - ID of MR
+ # source_branch - The source branch
+ # target_branch - The target branch
+ # assignee_id - Assignee user ID
+ # title - Title of MR
+ # closed - Status of MR. true - closed
+ # Example:
+ # PUT /projects/:id/merge_request/:merge_request_id
+ #
+ put ":id/merge_request/:merge_request_id" do
+ attrs = attributes_for_keys [:source_branch, :target_branch, :assignee_id, :title, :closed]
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+
+ authorize! :modify_merge_request, merge_request
+
+ if merge_request.update_attributes attrs
+ merge_request.reload_code
+ merge_request.mark_as_unchecked
+ present merge_request, with: Entities::MergeRequest
+ else
+ not_found!
+ end
+ end
+
+ # Post comment to merge request
+ #
+ # Parameters:
+ # id (required) - The ID or code name of a project
+ # merge_request_id (required) - ID of MR
+ # note (required) - Text of comment
+ # Examples:
+ # POST /projects/:id/merge_request/:merge_request_id/comments
+ #
+ post ":id/merge_request/:merge_request_id/comments" do
+ merge_request = user_project.merge_requests.find(params[:merge_request_id])
+ note = merge_request.notes.new(note: params[:note], project_id: user_project.id)
+ note.author = current_user
+
+ if note.save
+ present note, with: Entities::Note
+ else
+ not_found!
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 8f094e0c..ac20bbec 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -147,7 +147,7 @@ module Gitlab
@hooks = paginate user_project.hooks
present @hooks, with: Entities::Hook
end
-
+
# Get a project hook
#
# Parameters:
@@ -159,7 +159,7 @@ module Gitlab
@hook = user_project.hooks.find(params[:hook_id])
present @hook, with: Entities::Hook
end
-
+
# Add hook to project
#
@@ -177,7 +177,7 @@ module Gitlab
error!({'message' => '404 Not found'}, 404)
end
end
-
+
# Update an existing project hook
#
# Parameters:
@@ -382,13 +382,7 @@ module Gitlab
tree = Tree.new commit.tree, user_project, ref, params[:filepath]
not_found! "File" unless tree.try(:tree)
- if tree.text?
- encoding = Gitlab::Encode.detect_encoding(tree.data)
- content_type encoding ? "text/plain; charset=#{encoding}" : "text/plain"
- else
- content_type tree.mime_type
- end
-
+ content_type tree.mime_type
present tree.data
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 7f548aaa..57e0aa10 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -23,24 +23,23 @@ module Gitlab
@user = User.find(params[:id])
present @user, with: Entities::User
end
-
+
# Create user. Available only for admin
#
# Parameters:
# email (required) - Email
- # name (required) - Name
# password (required) - Password
- # password_confirmation (required) - Password confirmation
+ # name - Name
# skype - Skype ID
# linkedin - Linkedin
# twitter - Twitter account
- # projects_limit - Limit projects wich user can create
+ # projects_limit - Number of projects user can create
# Example Request:
# POST /users
post do
authenticated_as_admin!
- attrs = attributes_for_keys [:email, :name, :password, :password_confirmation, :skype, :linkedin, :twitter, :projects_limit]
- user = User.new attrs
+ attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit]
+ user = User.new attrs, as: :admin
if user.save
present user, with: Entities::User
else
diff --git a/lib/event_filter.rb b/lib/event_filter.rb
new file mode 100644
index 00000000..14ab0193
--- /dev/null
+++ b/lib/event_filter.rb
@@ -0,0 +1,68 @@
+class EventFilter
+ attr_accessor :params
+
+ class << self
+ def default_filter
+ %w{ push issues merge_requests team}
+ end
+
+ def push
+ 'push'
+ end
+
+ def merged
+ 'merged'
+ end
+
+ def comments
+ 'comments'
+ end
+
+ def team
+ 'team'
+ end
+ end
+
+ def initialize params
+ @params = if params
+ params.dup
+ else
+ []#EventFilter.default_filter
+ end
+ end
+
+ def apply_filter events
+ return events unless params.present?
+
+ filter = params.dup
+
+ actions = []
+ actions << Event::Pushed if filter.include? 'push'
+ actions << Event::Merged if filter.include? 'merged'
+
+ if filter.include? 'team'
+ actions << Event::Joined
+ actions << Event::Left
+ end
+
+ actions << Event::Commented if filter.include? 'comments'
+
+ events = events.where(action: actions)
+ end
+
+ def options key
+ filter = params.dup
+
+ if filter.include? key
+ filter.delete key
+ else
+ filter << key
+ end
+
+ filter
+ end
+
+ def active? key
+ params.include? key
+ end
+end
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index cb931861..7ae34de6 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -14,7 +14,10 @@ module Gitlab
end
def ga_repo
- @ga_repo ||= ::Gitolite::GitoliteAdmin.new(File.join(config_tmp_dir,'gitolite'))
+ @ga_repo ||= ::Gitolite::GitoliteAdmin.new(
+ File.join(config_tmp_dir,'gitolite'),
+ conf: Gitlab.config.gitolite_config_file
+ )
end
def apply
diff --git a/lib/gitlab/backend/grack_auth.rb b/lib/gitlab/backend/grack_auth.rb
index 766e3874..dd5a9bec 100644
--- a/lib/gitlab/backend/grack_auth.rb
+++ b/lib/gitlab/backend/grack_auth.rb
@@ -18,7 +18,7 @@ module Grack
@env['SCRIPT_NAME'] = ""
# Find project by PATH_INFO from env
- if m = /^\/([\w-]+).git/.match(@request.path_info).to_a
+ if m = /^\/([\w\.-]+)\.git/.match(@request.path_info).to_a
self.project = Project.find_by_path(m.last)
return false unless project
end
@@ -65,7 +65,7 @@ module Grack
end
# Need to reset seek point
@request.body.rewind
- /refs\/heads\/([\w-]+)/.match(input).to_a.first
+ /refs\/heads\/([\w\.-]+)/.match(input).to_a.first
end
protected
diff --git a/lib/gitlab/encode.rb b/lib/gitlab/encode.rb
deleted file mode 100644
index 7e37442e..00000000
--- a/lib/gitlab/encode.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# Patch Strings to enable detect_encoding! on views
-require 'charlock_holmes/string'
-module Gitlab
- module Encode
- extend self
-
- def utf8 message
- # return nil if message is nil
- return nil unless message
-
- message.force_encoding("utf-8")
- # return message if message type is binary
- detect = CharlockHolmes::EncodingDetector.detect(message)
- return message if detect[:type] == :binary
-
- # if message is utf-8 encoding, just return it
- return message if message.valid_encoding?
-
- # if message is not utf-8 encoding, convert it
- if detect[:encoding]
- message.force_encoding(detect[:encoding])
- message.encode!("utf-8", detect[:encoding], undef: :replace, replace: "", invalid: :replace)
- end
-
- # ensure message encoding is utf8
- message.valid_encoding? ? message : raise
-
- # Prevent app from crash cause of encoding errors
- rescue
- encoding = detect ? detect[:encoding] : "unknown"
- "--broken encoding: #{encoding}"
- end
-
- def detect_encoding message
- return nil unless message
-
- hash = CharlockHolmes::EncodingDetector.detect(message) rescue {}
- return hash[:encoding] ? hash[:encoding] : nil
- end
- end
-end
diff --git a/lib/gitlab/file_editor.rb b/lib/gitlab/file_editor.rb
deleted file mode 100644
index dc3f9480..00000000
--- a/lib/gitlab/file_editor.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-module Gitlab
- # GitLab file editor
- #
- # It gives you ability to make changes to files
- # & commit this changes from GitLab UI.
- class FileEditor
- attr_accessor :user, :project, :ref
-
- def initialize(user, project, ref)
- self.user = user
- self.project = project
- self.ref = ref
- end
-
- def update(path, content, commit_message, last_commit)
- return false unless can_edit?(path, last_commit)
-
- Grit::Git.with_timeout(10.seconds) do
- lock_file = Rails.root.join("tmp", "#{project.path}.lock")
-
- File.open(lock_file, "w+") do |f|
- f.flock(File::LOCK_EX)
-
- unless project.satellite.exists?
- raise "Satellite doesn't exist"
- end
-
- project.satellite.clear
-
- Dir.chdir(project.satellite.path) do
- r = Grit::Repo.new('.')
- r.git.sh "git reset --hard"
- r.git.sh "git fetch origin"
- r.git.sh "git config user.name \"#{user.name}\""
- r.git.sh "git config user.email \"#{user.email}\""
- r.git.sh "git checkout -b #{ref} origin/#{ref}"
- File.open(path, 'w'){|f| f.write(content)}
- r.git.sh "git add ."
- r.git.sh "git commit -am '#{commit_message}'"
- output = r.git.sh "git push origin #{ref}"
-
- if output =~ /reject/
- return false
- end
- end
- end
- end
- true
- end
-
- protected
-
- def can_edit?(path, last_commit)
- current_last_commit = @project.last_commit_for(ref, path).sha
- last_commit == current_last_commit
- end
- end
-end
diff --git a/lib/gitlab/git_stats.rb b/lib/gitlab/git_stats.rb
new file mode 100644
index 00000000..94374869
--- /dev/null
+++ b/lib/gitlab/git_stats.rb
@@ -0,0 +1,76 @@
+module Gitlab
+ class GitStats
+ attr_accessor :repo, :ref
+
+ def initialize repo, ref
+ @repo, @ref = repo, ref
+ end
+
+ def authors
+ @authors ||= collect_authors
+ end
+
+ def commits_count
+ @commits_count ||= repo.commit_count(ref)
+ end
+
+ def files_count
+ repo.git.sh("git ls-tree -r --name-only #{ref} | wc -l").first.to_i
+ end
+
+ def authors_count
+ authors.size
+ end
+
+ def graph
+ @graph ||= build_graph
+ end
+
+ protected
+
+ def collect_authors
+ shortlog = repo.git.shortlog({e: true, s: true }, ref)
+
+ authors = []
+
+ lines = shortlog.split("\n")
+
+ lines.each do |line|
+ data = line.split("\t")
+ commits = data.first
+ author = Grit::Actor.from_string(data.last)
+
+ authors << OpenStruct.new(
+ name: author.name,
+ email: author.email,
+ commits: commits.to_i
+ )
+ end
+
+ authors.sort_by(&:commits).reverse
+ end
+
+ def build_graph n = 4
+ from, to = (Date.today - n.weeks), Date.today
+
+ format = "--pretty=format:'%h|%at|%ai|%aE'"
+ commits_strings = repo.git.sh("git rev-list --since #{from.to_s(:date)} #{format} #{ref} | grep -v commit")[0].split("\n")
+
+ commits_dates = commits_strings.map do |string|
+ data = string.split("|")
+ date = data[2]
+ Time.parse(date).to_date.to_s(:date)
+ end
+
+ commits_per_day = from.upto(to).map do |day|
+ commits_dates.count(day.to_date.to_s(:date))
+ end
+
+ OpenStruct.new(
+ labels: from.upto(to).map { |day| day.stamp('Aug 23') },
+ commits: commits_per_day,
+ weeks: n
+ )
+ end
+ end
+end
diff --git a/lib/gitlab/graph/commit.rb b/lib/gitlab/graph/commit.rb
new file mode 100644
index 00000000..af8d7828
--- /dev/null
+++ b/lib/gitlab/graph/commit.rb
@@ -0,0 +1,48 @@
+require "grit"
+
+module Gitlab
+ module Graph
+ class Commit
+ include ActionView::Helpers::TagHelper
+
+ attr_accessor :time, :space, :refs
+
+ def initialize(commit)
+ @_commit = commit
+ @time = -1
+ @space = 0
+ end
+
+ def method_missing(m, *args, &block)
+ @_commit.send(m, *args, &block)
+ end
+
+ def to_graph_hash
+ h = {}
+ h[:parents] = self.parents.collect do |p|
+ [p.id,0,0]
+ end
+ h[:author] = author.name
+ h[:time] = time
+ h[:space] = space
+ h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
+ h[:id] = sha
+ h[:date] = date
+ h[:message] = escape_once(message)
+ h[:login] = author.email
+ h
+ end
+
+ def add_refs(ref_cache, repo)
+ if ref_cache.empty?
+ repo.refs.each do |ref|
+ ref_cache[ref.commit.id] ||= []
+ ref_cache[ref.commit.id] << ref
+ end
+ end
+ @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id)
+ @refs ||= []
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graph/json_builder.rb b/lib/gitlab/graph/json_builder.rb
new file mode 100644
index 00000000..c2c3fa66
--- /dev/null
+++ b/lib/gitlab/graph/json_builder.rb
@@ -0,0 +1,172 @@
+require "grit"
+
+module Gitlab
+ module Graph
+ class JsonBuilder
+ attr_accessor :days, :commits, :ref_cache, :repo
+
+ def self.max_count
+ @max_count ||= 650
+ end
+
+ def initialize project
+ @project = project
+ @repo = project.repo
+ @ref_cache = {}
+
+ @commits = collect_commits
+ @days = index_commits
+ end
+
+ def days_json
+ @days_json = @days.compact.map { |d| [d.day, d.strftime("%b")] }.to_json
+ end
+
+ def commits_json
+ @commits_json = @commits.map(&:to_graph_hash).to_json
+ end
+
+ protected
+
+ # Get commits from repository
+ #
+ def collect_commits
+ @commits = Grit::Commit.find_all(repo, nil, {max_count: self.class.max_count}).dup
+
+ # Decorate with app/models/commit.rb
+ @commits.map! { |commit| ::Commit.new(commit) }
+
+ # Decorate with lib/gitlab/graph/commit.rb
+ @commits.map! { |commit| Gitlab::Graph::Commit.new(commit) }
+
+ # add refs to each commit
+ @commits.each { |commit| commit.add_refs(ref_cache, repo) }
+
+ @commits
+ end
+
+ # Method is adding time and space on the
+ # list of commits. As well as returns date list
+ # corelated with time set on commits.
+ #
+ # @param [Array] comits to index
+ #
+ # @return [Array] list of commit dates corelated with time on commits
+ def index_commits
+ days, heads = [], []
+ map = {}
+
+ commits.reverse.each_with_index do |c,i|
+ c.time = i
+ days[i] = c.committed_date
+ map[c.id] = c
+ heads += c.refs unless c.refs.nil?
+ end
+
+ heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
+ # sort heads so the master is top and current branches are closer
+ heads.sort! do |a,b|
+ if a.name == "master"
+ -1
+ elsif b.name == "master"
+ 1
+ else
+ b.commit.committed_date <=> a.commit.committed_date
+ end
+ end
+
+ @_reserved = {}
+ days.each_index do |i|
+ @_reserved[i] = []
+ end
+
+ heads.each do |h|
+ if map.include? h.commit.id then
+ place_chain(map[h.commit.id], map)
+ end
+ end
+
+ days
+ end
+
+ # Add space mark on commit and its parents
+ #
+ # @param [Graph::Commit] the commit object.
+ # @param [Hash] map of commits
+ def place_chain(commit, map, parent_time = nil)
+ leaves = take_left_leaves(commit, map)
+ if leaves.empty?
+ return
+ end
+ space = find_free_space(leaves.last.time..leaves.first.time)
+ leaves.each{|l| l.space = space}
+ # and mark it as reserved
+ min_time = leaves.last.time
+ parents = leaves.last.parents.collect
+ parents.each do |p|
+ if map.include? p.id
+ parent = map[p.id]
+ if parent.time < min_time
+ min_time = parent.time
+ end
+ end
+ end
+ if parent_time.nil?
+ max_time = leaves.first.time
+ else
+ max_time = parent_time - 1
+ end
+ mark_reserved(min_time..max_time, space)
+
+ # Visit branching chains
+ leaves.each do |l|
+ parents = l.parents.collect.select{|p| map.include? p.id and map[p.id].space == 0}
+ for p in parents
+ place_chain(map[p.id], map, l.time)
+ end
+ end
+ end
+
+ def mark_reserved(time_range, space)
+ for day in time_range
+ @_reserved[day].push(space)
+ end
+ end
+
+ def find_free_space(time_range)
+ reserved = []
+ for day in time_range
+ reserved += @_reserved[day]
+ end
+ space = 1
+ while reserved.include? space do
+ space += 1
+ end
+ space
+ end
+
+ # Takes most left subtree branch of commits
+ # which don't have space mark yet.
+ #
+ # @param [Graph::Commit] the commit object.
+ # @param [Hash] map of commits
+ #
+ # @return [Array] list of branch commits
+ def take_left_leaves(commit, map)
+ leaves = []
+ leaves.push(commit) if commit.space.zero?
+
+ while true
+ parent = commit.parents.collect.select do |p|
+ map.include? p.id and map[p.id].space == 0
+ end
+
+ return leaves if parent.count.zero?
+
+ commit = map[parent.first.id]
+ leaves.push(commit)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graph_commit.rb b/lib/gitlab/graph_commit.rb
deleted file mode 100644
index d3668a99..00000000
--- a/lib/gitlab/graph_commit.rb
+++ /dev/null
@@ -1,185 +0,0 @@
-require "grit"
-
-module Gitlab
- class GraphCommit
- attr_accessor :time, :space
- attr_accessor :refs
-
- include ActionView::Helpers::TagHelper
-
- def self.to_graph(project)
- @repo = project.repo
- commits = Grit::Commit.find_all(@repo, nil, {max_count: 650})
-
- ref_cache = {}
-
- commits.map! {|c| GraphCommit.new(Commit.new(c))}
- commits.each { |commit| commit.add_refs(ref_cache, @repo) }
-
- days = GraphCommit.index_commits(commits)
- @days_json = days.compact.collect{|d| [d.day, d.strftime("%b")] }.to_json
- @commits_json = commits.map(&:to_graph_hash).to_json
-
- return @days_json, @commits_json
- end
-
- # Method is adding time and space on the
- # list of commits. As well as returns date list
- # corelated with time set on commits.
- #
- # @param [Array] comits to index
- #
- # @return [Array] list of commit dates corelated with time on commits
- def self.index_commits(commits)
- days, heads = [], []
- map = {}
-
- commits.reverse.each_with_index do |c,i|
- c.time = i
- days[i] = c.committed_date
- map[c.id] = c
- heads += c.refs unless c.refs.nil?
- end
-
- heads.select!{|h| h.is_a? Grit::Head or h.is_a? Grit::Remote}
- # sort heads so the master is top and current branches are closer
- heads.sort! do |a,b|
- if a.name == "master"
- -1
- elsif b.name == "master"
- 1
- else
- b.commit.committed_date <=> a.commit.committed_date
- end
- end
-
- @_reserved = {}
- days.each_index do |i|
- @_reserved[i] = []
- end
-
- heads.each do |h|
- if map.include? h.commit.id then
- place_chain(map[h.commit.id], map)
- end
- end
- days
- end
-
- # Add space mark on commit and its parents
- #
- # @param [GraphCommit] the commit object.
- # @param [Hash] map of commits
- def self.place_chain(commit, map, parent_time = nil)
- leaves = take_left_leaves(commit, map)
- if leaves.empty? then
- return
- end
- space = find_free_space(leaves.last.time..leaves.first.time)
- leaves.each{|l| l.space = space}
- # and mark it as reserved
- min_time = leaves.last.time
- parents = leaves.last.parents.collect
- parents.each do |p|
- if map.include? p.id then
- parent = map[p.id]
- if parent.time < min_time then
- min_time = parent.time
- end
- end
- end
- if parent_time.nil? then
- max_time = leaves.first.time
- else
- max_time = parent_time - 1
- end
- mark_reserved(min_time..max_time, space)
- # Visit branching chains
- leaves.each do |l|
- parents = l.parents.collect
- .select{|p| map.include? p.id and map[p.id].space == 0}
- for p in parents
- place_chain(map[p.id], map, l.time)
- end
- end
- end
-
- def self.mark_reserved(time_range, space)
- for day in time_range
- @_reserved[day].push(space)
- end
- end
-
- def self.find_free_space(time_range)
- reserved = []
- for day in time_range
- reserved += @_reserved[day]
- end
- space = 1
- while reserved.include? space do
- space += 1
- end
- space
- end
-
- # Takes most left subtree branch of commits
- # which don't have space mark yet.
- #
- # @param [GraphCommit] the commit object.
- # @param [Hash] map of commits
- #
- # @return [Array] list of branch commits
- def self.take_left_leaves(commit, map)
- leaves = []
- leaves.push(commit) if commit.space == 0
- while true
- parent = commit.parents.collect
- .select{|p| map.include? p.id and map[p.id].space == 0}
- if parent.count == 0 then
- return leaves
- else
- commit = map[parent.first.id]
- leaves.push(commit)
- end
- end
- end
-
-
- def initialize(commit)
- @_commit = commit
- @time = -1
- @space = 0
- end
-
- def method_missing(m, *args, &block)
- @_commit.send(m, *args, &block)
- end
-
- def to_graph_hash
- h = {}
- h[:parents] = self.parents.collect do |p|
- [p.id,0,0]
- end
- h[:author] = Gitlab::Encode.utf8(author.name)
- h[:time] = time
- h[:space] = space
- h[:refs] = refs.collect{|r|r.name}.join(" ") unless refs.nil?
- h[:id] = sha
- h[:date] = date
- h[:message] = escape_once(Gitlab::Encode.utf8(message))
- h[:login] = author.email
- h
- end
-
- def add_refs(ref_cache, repo)
- if ref_cache.empty?
- repo.refs.each do |ref|
- ref_cache[ref.commit.id] ||= []
- ref_cache[ref.commit.id] << ref
- end
- end
- @refs = ref_cache[@_commit.id] if ref_cache.include?(@_commit.id)
- @refs ||= []
- end
- end
-end
diff --git a/lib/gitlab/merge.rb b/lib/gitlab/merge.rb
deleted file mode 100644
index bf7aaa51..00000000
--- a/lib/gitlab/merge.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-module Gitlab
- class Merge
- attr_accessor :merge_request, :project, :user
-
- def initialize(merge_request, user)
- @merge_request = merge_request
- @project = merge_request.project
- @user = user
- end
-
- def can_be_merged?
- in_locked_and_timed_satellite do |merge_repo|
- merge_in_satellite!(merge_repo)
- end
- end
-
- # Merges the source branch into the target branch in the satellite and
- # pushes it back to Gitolite.
- # It also removes the source branch if requested in the merge request.
- #
- # Returns false if the merge produced conflicts
- # Returns false if pushing from the satallite to Gitolite failed or was rejected
- # Returns true otherwise
- def merge!
- in_locked_and_timed_satellite do |merge_repo|
- if merge_in_satellite!(merge_repo)
- # push merge back to Gitolite
- # will raise CommandFailed when push fails
- merge_repo.git.push({raise: true}, :origin, merge_request.target_branch)
-
- # remove source branch
- if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch)
- # will raise CommandFailed when push fails
- merge_repo.git.push({raise: true}, :origin, ":#{merge_request.source_branch}")
- end
-
- # merge, push and branch removal successful
- true
- end
- end
- rescue Grit::Git::CommandFailed
- false
- end
-
- private
-
- # * Sets a 30s timeout for Git
- # * Locks the satellite repo
- # * Yields the prepared satallite repo
- def in_locked_and_timed_satellite
- Grit::Git.with_timeout(30.seconds) do
- lock_file = Rails.root.join("tmp", "#{project.path}.lock")
-
- File.open(lock_file, "w+") do |f|
- f.flock(File::LOCK_EX)
-
- unless project.satellite.exists?
- raise "Satellite doesn't exist"
- end
-
- Dir.chdir(project.satellite.path) do
- repo = Grit::Repo.new('.')
-
- return yield repo
- end
- end
- end
- rescue Errno::ENOMEM => ex
- Gitlab::GitLogger.error(ex.message)
- rescue Grit::Git::GitTimeout
- return false
- end
-
- # Merges the source_branch into the target_branch in the satellite.
- #
- # Note: it will clear out the satellite before doing anything
- #
- # Returns false if the merge produced conflicts
- # Returns true otherwise
- def merge_in_satellite!(repo)
- prepare_satelite!(repo)
-
- # create target branch in satellite at the corresponding commit from Gitolite
- repo.git.checkout({b: true}, merge_request.target_branch, "origin/#{merge_request.target_branch}")
-
- # merge the source branch from Gitolite into the satellite
- # will raise CommandFailed when merge fails
- repo.git.pull({no_ff: true, raise: true}, :origin, merge_request.source_branch)
- rescue Grit::Git::CommandFailed
- false
- end
-
- # * Clears the satellite
- # * Updates the satellite from Gitolite
- # * Sets up Git variables for the user
- def prepare_satelite!(repo)
- project.satellite.clear
-
- repo.git.reset(hard: true)
- repo.git.fetch({}, :origin)
-
- repo.git.config({}, "user.name", user.name)
- repo.git.config({}, "user.email", user.email)
- end
- end
-end
diff --git a/lib/gitlab/satellite.rb b/lib/gitlab/satellite.rb
deleted file mode 100644
index 9d8dfb8e..00000000
--- a/lib/gitlab/satellite.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-module Gitlab
- class Satellite
-
- PARKING_BRANCH = "__parking_branch"
-
- attr_accessor :project
-
- def initialize project
- self.project = project
- end
-
- def create
- `git clone #{project.url_to_repo} #{path}`
- end
-
- def path
- Rails.root.join("tmp", "repo_satellites", project.path)
- end
-
- def exists?
- File.exists? path
- end
-
- #will be deleted all branches except PARKING_BRANCH
- def clear
- Dir.chdir(path) do
- heads = Grit::Repo.new(".").heads.map{|head| head.name}
- if heads.include? PARKING_BRANCH
- `git checkout #{PARKING_BRANCH}`
- else
- `git checkout -b #{PARKING_BRANCH}`
- end
- heads.delete(PARKING_BRANCH)
- heads.each do |head|
- `git branch -D #{head}`
- end
- end
- end
-
- end
-end
diff --git a/lib/gitlab/satellite/action.rb b/lib/gitlab/satellite/action.rb
new file mode 100644
index 00000000..ed2541f3
--- /dev/null
+++ b/lib/gitlab/satellite/action.rb
@@ -0,0 +1,46 @@
+module Gitlab
+ module Satellite
+ class Action
+ DEFAULT_OPTIONS = { git_timeout: 30.seconds }
+
+ attr_accessor :options, :project, :user
+
+ def initialize(user, project, options = {})
+ @options = DEFAULT_OPTIONS.merge(options)
+ @project = project
+ @user = user
+ end
+
+ protected
+
+ # * Sets a 30s timeout for Git
+ # * Locks the satellite repo
+ # * Yields the prepared satellite repo
+ def in_locked_and_timed_satellite
+ Grit::Git.with_timeout(options[:git_timeout]) do
+ project.satellite.lock do
+ return yield project.satellite.repo
+ end
+ end
+ rescue Errno::ENOMEM => ex
+ Gitlab::GitLogger.error(ex.message)
+ return false
+ rescue Grit::Git::GitTimeout => ex
+ Gitlab::GitLogger.error(ex.message)
+ return false
+ end
+
+ # * Clears the satellite
+ # * Updates the satellite from Gitolite
+ # * Sets up Git variables for the user
+ #
+ # Note: use this within #in_locked_and_timed_satellite
+ def prepare_satellite!(repo)
+ project.satellite.clear_and_update!
+
+ repo.git.config({}, "user.name", user.name)
+ repo.git.config({}, "user.email", user.email)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/edit_file_action.rb b/lib/gitlab/satellite/edit_file_action.rb
new file mode 100644
index 00000000..336afc88
--- /dev/null
+++ b/lib/gitlab/satellite/edit_file_action.rb
@@ -0,0 +1,57 @@
+module Gitlab
+ module Satellite
+ # GitLab server-side file update and commit
+ class EditFileAction < Action
+ attr_accessor :file_path, :ref
+
+ def initialize(user, project, ref, file_path)
+ super user, project, git_timeout: 10.seconds
+ @file_path = file_path
+ @ref = ref
+ end
+
+ # Updates the files content and creates a new commit for it
+ #
+ # Returns false if the ref has been updated while editing the file
+ # Returns false if commiting the change fails
+ # Returns false if pushing from the satellite to Gitolite failed or was rejected
+ # Returns true otherwise
+ def commit!(content, commit_message, last_commit)
+ return false unless can_edit?(last_commit)
+
+ in_locked_and_timed_satellite do |repo|
+ prepare_satellite!(repo)
+
+ # create target branch in satellite at the corresponding commit from Gitolite
+ repo.git.checkout({raise: true, timeout: true, b: true}, ref, "origin/#{ref}")
+
+ # update the file in the satellite's working dir
+ file_path_in_satellite = File.join(repo.working_dir, file_path)
+ File.open(file_path_in_satellite, 'w') { |f| f.write(content) }
+
+ # commit the changes
+ # will raise CommandFailed when commit fails
+ repo.git.commit(raise: true, timeout: true, a: true, m: commit_message)
+
+
+ # push commit back to Gitolite
+ # will raise CommandFailed when push fails
+ repo.git.push({raise: true, timeout: true}, :origin, ref)
+
+ # everything worked
+ true
+ end
+ rescue Grit::Git::CommandFailed => ex
+ Gitlab::GitLogger.error(ex.message)
+ false
+ end
+
+ protected
+
+ def can_edit?(last_commit)
+ current_last_commit = @project.last_commit_for(ref, file_path).sha
+ last_commit == current_last_commit
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/merge_action.rb b/lib/gitlab/satellite/merge_action.rb
new file mode 100644
index 00000000..832db662
--- /dev/null
+++ b/lib/gitlab/satellite/merge_action.rb
@@ -0,0 +1,71 @@
+module Gitlab
+ module Satellite
+ # GitLab server-side merge
+ class MergeAction < Action
+ attr_accessor :merge_request
+
+ def initialize(user, merge_request)
+ super user, merge_request.project
+ @merge_request = merge_request
+ end
+
+ # Checks if a merge request can be executed without user interaction
+ def can_be_merged?
+ in_locked_and_timed_satellite do |merge_repo|
+ merge_in_satellite!(merge_repo)
+ end
+ end
+
+ # Merges the source branch into the target branch in the satellite and
+ # pushes it back to Gitolite.
+ # It also removes the source branch if requested in the merge request.
+ #
+ # Returns false if the merge produced conflicts
+ # Returns false if pushing from the satellite to Gitolite failed or was rejected
+ # Returns true otherwise
+ def merge!
+ in_locked_and_timed_satellite do |merge_repo|
+ if merge_in_satellite!(merge_repo)
+ # push merge back to Gitolite
+ # will raise CommandFailed when push fails
+ merge_repo.git.push({raise: true, timeout: true}, :origin, merge_request.target_branch)
+
+ # remove source branch
+ if merge_request.should_remove_source_branch && !project.root_ref?(merge_request.source_branch)
+ # will raise CommandFailed when push fails
+ merge_repo.git.push({raise: true, timeout: true}, :origin, ":#{merge_request.source_branch}")
+ end
+
+ # merge, push and branch removal successful
+ true
+ end
+ end
+ rescue Grit::Git::CommandFailed => ex
+ Gitlab::GitLogger.error(ex.message)
+ false
+ end
+
+ private
+
+ # Merges the source_branch into the target_branch in the satellite.
+ #
+ # Note: it will clear out the satellite before doing anything
+ #
+ # Returns false if the merge produced conflicts
+ # Returns true otherwise
+ def merge_in_satellite!(repo)
+ prepare_satellite!(repo)
+
+ # create target branch in satellite at the corresponding commit from Gitolite
+ repo.git.checkout({raise: true, timeout: true, b: true}, merge_request.target_branch, "origin/#{merge_request.target_branch}")
+
+ # merge the source branch from Gitolite into the satellite
+ # will raise CommandFailed when merge fails
+ repo.git.pull({raise: true, timeout: true, no_ff: true}, :origin, merge_request.source_branch)
+ rescue Grit::Git::CommandFailed => ex
+ Gitlab::GitLogger.error(ex.message)
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/satellite/satellite.rb b/lib/gitlab/satellite/satellite.rb
new file mode 100644
index 00000000..28b6f538
--- /dev/null
+++ b/lib/gitlab/satellite/satellite.rb
@@ -0,0 +1,92 @@
+module Gitlab
+ module Satellite
+ class Satellite
+ PARKING_BRANCH = "__parking_branch"
+
+ attr_accessor :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def clear_and_update!
+ raise "Satellite doesn't exist" unless exists?
+
+ delete_heads!
+ clear_working_dir!
+ update_from_source!
+ end
+
+ def create
+ `git clone #{project.url_to_repo} #{path}`
+ end
+
+ def exists?
+ File.exists? path
+ end
+
+ # * Locks the satellite
+ # * Changes the current directory to the satellite's working dir
+ # * Yields
+ def lock
+ raise "Satellite doesn't exist" unless exists?
+
+ File.open(lock_file, "w+") do |f|
+ f.flock(File::LOCK_EX)
+
+ Dir.chdir(path) do
+ return yield
+ end
+ end
+ end
+
+ def lock_file
+ Rails.root.join("tmp", "#{project.path}.lock")
+ end
+
+ def path
+ Rails.root.join("tmp", "repo_satellites", project.path)
+ end
+
+ def repo
+ raise "Satellite doesn't exist" unless exists?
+
+ @repo ||= Grit::Repo.new(path)
+ end
+
+ private
+
+ # Clear the working directory
+ def clear_working_dir!
+ repo.git.reset(hard: true)
+ end
+
+ # Deletes all branches except the parking branch
+ #
+ # This ensures we have no name clashes or issues updating branches when
+ # working with the satellite.
+ def delete_heads!
+ heads = repo.heads.map(&:name)
+
+ # update or create the parking branch
+ if heads.include? PARKING_BRANCH
+ repo.git.checkout({}, PARKING_BRANCH)
+ else
+ repo.git.checkout({b: true}, PARKING_BRANCH)
+ end
+
+ # remove the parking branch from the list of heads ...
+ heads.delete(PARKING_BRANCH)
+ # ... and delete all others
+ heads.each { |head| repo.git.branch({D: true}, head) }
+ end
+
+ # Updates the satellite from Gitolite
+ #
+ # Note: this will only update remote branches (i.e. origin/*)
+ def update_from_source!
+ repo.git.fetch({timeout: true}, :origin)
+ end
+ end
+ end
+end
diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb
index 30a80714..48b4da9d 100644
--- a/lib/redcarpet/render/gitlab_html.rb
+++ b/lib/redcarpet/render/gitlab_html.rb
@@ -10,10 +10,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
end
def block_code(code, language)
+ options = { options: {encoding: 'utf-8'} }
+
if Pygments::Lexer.find(language)
- Pygments.highlight(code, lexer: language, options: {encoding: 'utf-8'})
+ Pygments.highlight(code, options.merge(lexer: language.downcase))
else
- Pygments.highlight(code, options: {encoding: 'utf-8'})
+ Pygments.highlight(code, options)
end
end
diff --git a/lib/tasks/bulk_import.rake b/lib/tasks/bulk_import.rake
deleted file mode 100644
index 914f920a..00000000
--- a/lib/tasks/bulk_import.rake
+++ /dev/null
@@ -1,83 +0,0 @@
-desc "Imports existing Git repos from a directory into new projects in git_base_path"
-task :import_projects, [:directory,:email] => :environment do |t, args|
- user_email, import_directory = args.email, args.directory
- repos_to_import = Dir.glob("#{import_directory}/*")
- git_base_path = Gitlab.config.git_base_path
- imported_count, skipped_count, failed_count = 0
-
- puts "Found #{repos_to_import.size} repos to import"
-
- repos_to_import.each do |repo_path|
- repo_name = File.basename repo_path
- clone_path = "#{git_base_path}#{repo_name}.git"
-
- puts " Processing #{repo_name}"
-
- if Dir.exists? clone_path
- if Project.find_by_code(repo_name)
- puts " INFO: #{clone_path} already exists in repositories directory, skipping."
- skipped_count += 1
- next
- else
- puts " INFO: Project doesn't exist for #{repo_name} (but the repo does)."
- end
- else
- # Clone the repo
- unless clone_bare_repo_as_git(repo_path, clone_path)
- failed_count += 1
- next
- end
- end
-
- # Create the project and repo
- if create_repo_project(repo_name, user_email)
- imported_count += 1
- else
- failed_count += 1
- end
- end
-
- puts "Finished importing #{imported_count} projects (skipped #{skipped_count}, failed #{failed_count})."
-end
-
-# Clones a repo as bare git repo using the git_user
-def clone_bare_repo_as_git(existing_path, new_path)
- git_user = Gitlab.config.ssh_user
- begin
- sh "sudo -u #{git_user} -i git clone --bare '#{existing_path}' #{new_path}"
- rescue Exception => msg
- puts " ERROR: Failed to clone #{existing_path} to #{new_path}"
- puts " Make sure #{git_user} can reach #{existing_path}"
- puts " Exception-MSG: #{msg}"
- end
-end
-
-# Creates a project in GitLab given a `project_name` to use
-# (for name, web url, and code url) and a `user_email` that will be
-# assigned as the owner of the project.
-def create_repo_project(project_name, user_email)
- if user = User.find_by_email(user_email)
- # Using find_by_code since that's the most important identifer to be unique
- if Project.find_by_code(project_name)
- puts " INFO: Project #{project_name} already exists in Gitlab, skipping."
- else
- project = Project.create(
- name: project_name,
- code: project_name,
- path: project_name,
- owner: user,
- description: "Automatically created from 'import_projects' rake task on #{Time.now}"
- )
-
- if project.valid?
- # Add user as admin for project
- project.users_projects.create!(:project_access => UsersProject::MASTER, :user => user)
- project.update_repository
- else
- puts " ERROR: Failed to create project #{project} because #{project.errors.first}"
- end
- end
- else
- puts " ERROR: user with #{user_email} not found, skipping"
- end
-end
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
new file mode 100644
index 00000000..09f0dc9e
--- /dev/null
+++ b/lib/tasks/gitlab/import.rake
@@ -0,0 +1,54 @@
+namespace :gitlab do
+ namespace :import do
+ # How to use:
+ #
+ # 1. copy your bare repos under git base_path
+ # 2. run bundle exec rake gitlab:import:repos RAILS_ENV=production
+ #
+ # Notes:
+ # * project owner will be a first admin
+ # * existing projects will be skipped
+ #
+ desc "GITLAB | Import bare repositories from git_host -> base_path into GitLab project instance"
+ task :repos => :environment do
+
+ git_base_path = Gitlab.config.git_base_path
+ repos_to_import = Dir.glob(git_base_path + '/*')
+
+ repos_to_import.each do |repo_path|
+ repo_name = File.basename repo_path
+
+ # skip gitolite admin
+ next if repo_name == 'gitolite-admin.git'
+
+ path = repo_name.sub(/\.git$/, '')
+
+ project = Project.find_by_path(path)
+
+ puts "Processing #{repo_name}".yellow
+
+ if project
+ puts " * #{project.name} (#{repo_name}) exists"
+ else
+ user = User.admins.first
+
+ project_params = {
+ :name => path,
+ :code => path,
+ :path => path,
+ }
+
+ project = Project.create_by_user(project_params, user)
+
+ if project.valid?
+ puts " * Created #{project.name} (#{repo_name})".green
+ else
+ puts " * Failed trying to create #{project.name} (#{repo_name})".red
+ end
+ end
+ end
+
+ puts "Done!".green
+ end
+ end
+end
diff --git a/lib/tasks/gitlab/status.rake b/lib/tasks/gitlab/status.rake
index ab2f41af..508c41a2 100644
--- a/lib/tasks/gitlab/status.rake
+++ b/lib/tasks/gitlab/status.rake
@@ -65,7 +65,7 @@ namespace :gitlab do
end
print "UMASK for .gitolite.rc is 0007? ............"
- if open("#{git_base_path}/../.gitolite.rc").grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?
+ if open(File.absolute_path("#{git_base_path}/../.gitolite.rc")).grep(/UMASK([ \t]*)=([ \t>]*)0007/).any?
puts "YES".green
else
puts "NO".red
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index be40c561..0faca766 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -16,6 +16,7 @@
# st_diffs :text(4294967295
# merged :boolean default(FALSE), not null
# state :integer default(1), not null
+# milestone_id :integer
#
require 'spec_helper'
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
new file mode 100644
index 00000000..e1c7949f
--- /dev/null
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -0,0 +1,62 @@
+require "spec_helper"
+
+describe Gitlab::API do
+ include ApiHelpers
+
+ let(:user) { Factory :user }
+ let!(:project) { Factory :project, owner: user }
+ let!(:merge_request) { Factory :merge_request, author: user, assignee: user, project: project, title: "Test" }
+ before { project.add_access(user, :read) }
+
+ describe "GET /projects/:id/merge_requests" do
+ context "when unauthenticated" do
+ it "should return authentication error" do
+ get api("/projects/#{project.code}/merge_requests")
+ response.status.should == 401
+ end
+ end
+
+ context "when authenticated" do
+ it "should return an array of merge_requests" do
+ get api("/projects/#{project.code}/merge_requests", user)
+ response.status.should == 200
+ json_response.should be_an Array
+ json_response.first['title'].should == merge_request.title
+ end
+ end
+ end
+
+ describe "GET /projects/:id/merge_request/:merge_request_id" do
+ it "should return merge_request" do
+ get api("/projects/#{project.code}/merge_request/#{merge_request.id}", user)
+ response.status.should == 200
+ json_response['title'].should == merge_request.title
+ end
+ end
+
+ describe "POST /projects/:id/merge_requests" do
+ it "should return merge_request" do
+ post api("/projects/#{project.code}/merge_requests", user),
+ title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user
+ response.status.should == 201
+ json_response['title'].should == 'Test merge_request'
+ end
+ end
+
+ describe "PUT /projects/:id/merge_request/:merge_request_id" do
+ it "should return merge_request" do
+ put api("/projects/#{project.code}/merge_request/#{merge_request.id}", user), title: "New title"
+ response.status.should == 200
+ json_response['title'].should == 'New title'
+ end
+ end
+
+ describe "POST /projects/:id/merge_request/:merge_request_id/comments" do
+ it "should return comment" do
+ post api("/projects/#{project.code}/merge_request/#{merge_request.id}/comments", user), note: "My comment"
+ response.status.should == 201
+ json_response['note'].should == 'My comment'
+ end
+ end
+
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 51526f89..5f9a587d 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -46,7 +46,7 @@ describe Gitlab::API do
response.status.should == 201
end
- it "should repsond with 404 on failure" do
+ it "should respond with 404 on failure" do
post api("/projects", user)
response.status.should == 404
end
@@ -188,16 +188,16 @@ describe Gitlab::API do
}.to change {project.hooks.count}.by(1)
end
end
-
+
describe "PUT /projects/:id/hooks/:hook_id" do
it "should update an existing project hook" do
put api("/projects/#{project.code}/hooks/#{hook.id}", user),
- url: 'http://example.com'
+ url: 'http://example.org'
response.status.should == 200
- json_response['url'].should == 'http://example.com'
+ json_response['url'].should == 'http://example.org'
end
end
-
+
describe "DELETE /projects/:id/hooks" do
it "should delete hook from project" do
@@ -239,7 +239,7 @@ describe Gitlab::API do
end
describe "GET /projects/:id/snippets" do
- it "should return a project snippet" do
+ it "should return an array of project snippets" do
get api("/projects/#{project.code}/snippets", user)
response.status.should == 200
json_response.should be_an Array
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index e3049e09..4c2e6ada 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::API do
include ApiHelpers
let(:user) { Factory :user }
- let(:admin) {Factory :admin}
+ let(:admin) { Factory :admin }
let(:key) { Factory :key, user: user }
describe "GET /users" do
@@ -42,9 +42,9 @@ describe Gitlab::API do
end
it "should create user" do
- expect{
- post api("/users", admin), Factory.attributes(:user)
- }.to change{User.count}.by(1)
+ expect {
+ post api("/users", admin), Factory.attributes(:user, projects_limit: 3)
+ }.to change { User.count }.by(1)
end
it "shouldn't available for non admin users" do
diff --git a/spec/requests/gitlab_flavored_markdown_spec.rb b/spec/requests/gitlab_flavored_markdown_spec.rb
index 106f6451..014f99eb 100644
--- a/spec/requests/gitlab_flavored_markdown_spec.rb
+++ b/spec/requests/gitlab_flavored_markdown_spec.rb
@@ -80,12 +80,6 @@ describe "Gitlab Flavored Markdown" do
page.should have_link("##{issue.id}")
end
-
- it "should render title in repositories#tags" do
- visit tags_project_repository_path(project)
-
- page.should have_link("##{issue.id}")
- end
end
describe "for issues" do
diff --git a/vendor/assets/javascripts/g.bar-min.js b/vendor/assets/javascripts/g.bar-min.js
new file mode 100644
index 00000000..42f452af
--- /dev/null
+++ b/vendor/assets/javascripts/g.bar-min.js
@@ -0,0 +1,7 @@
+/*!
+ * g.Raphael 0.5 - Charting library, based on Raphaël
+ *
+ * Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+(function(){var f=Math.min,a=Math.max;function e(o,m,h,p,j,k,l,i){var s,n={round:"round",sharp:"sharp",soft:"soft",square:"square"};if((j&&!p)||(!j&&!h)){return l?"":i.path()}k=n[k]||"square";p=Math.round(p);h=Math.round(h);o=Math.round(o);m=Math.round(m);switch(k){case"round":if(!j){var g=~~(p/2);if(h=2*a?e.attr({path:["M",b,f+a,"a",a,a,0,1,1,0,2*-a,a,a,0,1,1,0,2*a,"m",0,2*-a-3,"a",a+3,a+3,0,1,0,0,2*(a+3),"L",b+a+3,f+c.height/2+3,"l",c.width+6,0,
+0,-c.height-6,-c.width-6,0,"L",b,f-a-3].join()}):(g=Math.sqrt(Math.pow(a+3,2)-Math.pow(c.height/2+3,2)),e.attr({path:["M",b,f+a,"c",-i,0,-a,i-a,-a,-a,0,-i,a-i,-a,a,-a,i,0,a,a-i,a,a,0,i,i-a,a,-a,a,"M",b+g,f-c.height/2-3,"a",a+3,a+3,0,1,0,0,c.height+6,"l",a+3-g+c.width+6,0,0,-c.height-6,"L",b+g,f-c.height/2-3].join()}));d=360-d;e.rotate(d,b,f);this.attrs?(this.attr(this.attrs.x?"x":"cx",b+a+3+(!h?"text"==this.type?c.width:0:c.width/2)).attr("y",h?f:f-c.height/2),this.rotate(d,b,f),90d&&this.attr(this.attrs.x?
+"x":"cx",b-a-3-(!h?c.width:c.width/2)).rotate(180,b,f)):90d?(this.translate(b-c.x-c.width-a-3,f-c.y-c.height/2),this.rotate(d-180,c.x+c.width+a+3,c.y+c.height/2)):(this.translate(b-c.x+a+3,f-c.y-c.height/2),this.rotate(d,c.x-a-3,c.y+c.height/2));return e.insertBefore(this.node?this:this[0])}};
+Raphael.el.drop=function(d,a,b){var f=this.getBBox(),e=this.paper||this[0].paper,c,g;if(e){switch(this.type){case "text":case "circle":case "ellipse":c=!0;break;default:c=!1}d=d||0;a="number"==typeof a?a:c?f.x+f.width/2:f.x;b="number"==typeof b?b:c?f.y+f.height/2:f.y;g=Math.max(f.width,f.height)+Math.min(f.width,f.height);e=e.path(["M",a,b,"l",g,0,"A",0.4*g,0.4*g,0,1,0,a+0.7*g,b-0.7*g,"z"]).attr({fill:"#000",stroke:"none"}).rotate(22.5-d,a,b);d=(d+90)*Math.PI/180;a=a+g*Math.sin(d)-(c?0:f.width/2);
+d=b+g*Math.cos(d)-(c?0:f.height/2);this.attrs?this.attr(this.attrs.x?"x":"cx",a).attr(this.attrs.y?"y":"cy",d):this.translate(a-f.x,d-f.y);return e.insertBefore(this.node?this:this[0])}};
+Raphael.el.flag=function(d,a,b){var f=this.paper||this[0].paper;if(f){var f=f.path().attr({fill:"#000",stroke:"#000"}),e=this.getBBox(),c=e.height/2,g;switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}d=d||0;a="number"==typeof a?a:g?e.x+e.width/2:e.x;b="number"==typeof b?b:g?e.y+e.height/2:e.y;f.attr({path:["M",a,b,"l",c+3,-c-3,e.width+6,0,0,e.height+6,-e.width-6,0,"z"].join()});d=360-d;f.rotate(d,a,b);this.attrs?(this.attr(this.attrs.x?"x":"cx",a+c+3+(!g?"text"==
+this.type?e.width:0:e.width/2)).attr("y",g?b:b-e.height/2),this.rotate(d,a,b),90d&&this.attr(this.attrs.x?"x":"cx",a-c-3-(!g?e.width:e.width/2)).rotate(180,a,b)):90d?(this.translate(a-e.x-e.width-c-3,b-e.y-e.height/2),this.rotate(d-180,e.x+e.width+c+3,e.y+e.height/2)):(this.translate(a-e.x+c+3,b-e.y-e.height/2),this.rotate(d,e.x-c-3,e.y+e.height/2));return f.insertBefore(this.node?this:this[0])}};
+Raphael.el.label=function(){var d=this.getBBox(),a=this.paper||this[0].paper,b=Math.min(20,d.width+10,d.height+10)/2;if(a)return a.rect(d.x-b/2,d.y-b/2,d.width+b,d.height+b,b).attr({stroke:"none",fill:"#000"}).insertBefore(this.node?this:this[0])};
+Raphael.el.blob=function(d,a,b){var f=this.getBBox(),e=Math.PI/180,c=this.paper||this[0].paper,g,i;if(c){switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}c=c.path().attr({fill:"#000",stroke:"none"});d=(+d+1?d:45)+90;i=Math.min(f.height,f.width);var a="number"==typeof a?a:g?f.x+f.width/2:f.x,b="number"==typeof b?b:g?f.y+f.height/2:f.y,h=Math.max(f.width+i,25*i/12),j=Math.max(f.height+i,25*i/12);g=a+i*Math.sin((d-22.5)*e);var o=b+i*Math.cos((d-22.5)*e),l=a+i*Math.sin((d+
+22.5)*e),d=b+i*Math.cos((d+22.5)*e),e=(l-g)/2;i=(d-o)/2;var h=h/2,j=j/2,n=-Math.sqrt(Math.abs(h*h*j*j-h*h*i*i-j*j*e*e)/(h*h*i*i+j*j*e*e));i=n*h*i/j+(l+g)/2;e=n*-j*e/h+(d+o)/2;c.attr({x:i,y:e,path:["M",a,b,"L",l,d,"A",h,j,0,1,1,g,o,"z"].join()});this.translate(i-f.x-f.width/2,e-f.y-f.height/2);return c.insertBefore(this.node?this:this[0])}};Raphael.fn.label=function(d,a,b){var f=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return f.push(b.label(),b)};
+Raphael.fn.popup=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.popup(f,e),b)};Raphael.fn.tag=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.tag(f,e),b)};Raphael.fn.flag=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.flag(f),b)};Raphael.fn.drop=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.drop(f),b)};
+Raphael.fn.blob=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.blob(f),b)};Raphael.el.lighter=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].b=Math.min(a[0].b*d,1);a[0].s/=d;a[1].b=Math.min(a[1].b*d,1);a[1].s/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};
+Raphael.el.darker=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].s=Math.min(a[0].s*d,1);a[0].b/=d;a[1].s=Math.min(a[1].s*d,1);a[1].b/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};Raphael.el.resetBrightness=function(){this.fs&&(this.attr({fill:this.fs[0],stroke:this.fs[1]}),delete this.fs);return this};
+(function(){var d=["lighter","darker","resetBrightness"],a="popup tag flag label drop blob".split(" "),b;for(b in a)(function(a){Raphael.st[a]=function(){return Raphael.el[a].apply(this,arguments)}})(a[b]);for(b in d)(function(a){Raphael.st[a]=function(){for(var b=0;bb;b++)bMath.abs(a-0.5)?~~a+0.5:Math.round(a)}var e=d,c=a;if(e==c)return{from:e,to:c,power:0};var e=(c-e)/b,g=c=~~e,b=0;if(c){for(;g;)b--,g=~~(e*Math.pow(10,b))/Math.pow(10,b);
+b++}else{if(0==e||!isFinite(e))b=1;else for(;!c;)b=b||1,c=~~(e*Math.pow(10,b))/Math.pow(10,b),b++;b&&b--}c=f(a*Math.pow(10,b))/Math.pow(10,b);c=a-b;)"-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),m+0.5,"l",2*j+1,0])),n.push(o.text(d+p,m,i&&i[u++]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})),k+=t,m-=s;Math.round(m+s-(a-b))&&("-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),a-b+0.5,"l",2*j+1,0])),n.push(o.text(d+
+p,a-b,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})))}else{for(var k=p,r=(0=q.x-5?n.pop(n.length-1).remove():w=q.x+q.width,k+=t,m+=s;Math.round(m-s-d-b)&&("-"!=h&&" "!=h&&(l=l.concat(["M",d+b+0.5,a-("+"==h?j:2*!!g*j),"l",0,2*j+1])),n.push(o.text(d+
+b,a+p,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v)))}l=o.path(l);l.text=n;l.all=o.set([l,n]);l.remove=function(){this.text.remove();this.constructor.prototype.remove.call(this)};return l},labelise:function(d,a,b){return d?(d+"").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g,function(d,e,c){if(e)return(+a).toFixed(e.replace(/^#+\.?/g,"").length);if(c)return(100*a/b).toFixed(c.replace(/^%+\.?/g,"").length)+"%"}):(+a).toFixed(0)}};
\ No newline at end of file