Merge branch 'master' of git://github.com/gitlabhq/gitlabhq
This commit is contained in:
commit
48443d20ca
114 changed files with 1524 additions and 1674 deletions
|
@ -1,3 +0,0 @@
|
||||||
#this code temporarily disables notes for all controllers
|
|
||||||
# Footnotes::Filter.notes = []
|
|
||||||
|
|
10
CHANGELOG
10
CHANGELOG
|
@ -1,8 +1,18 @@
|
||||||
|
v 2.8.1
|
||||||
|
- ability to disable gravatars
|
||||||
|
- improved MR diff logic
|
||||||
|
- ssh key help page
|
||||||
|
|
||||||
v 2.8.0
|
v 2.8.0
|
||||||
- Gitlab Flavored Markdown
|
- Gitlab Flavored Markdown
|
||||||
- Bulk issues update
|
- Bulk issues update
|
||||||
- Issues API
|
- Issues API
|
||||||
- Cucumber coverage increased
|
- Cucumber coverage increased
|
||||||
|
- Post-receive files fixed
|
||||||
|
- UI improved
|
||||||
|
- Application cleanup
|
||||||
|
- more cucumber
|
||||||
|
- capybara-webkit + headless
|
||||||
|
|
||||||
v 2.7.0
|
v 2.7.0
|
||||||
- Issue Labels
|
- Issue Labels
|
||||||
|
|
16
Gemfile
16
Gemfile
|
@ -58,7 +58,7 @@ gem "unicorn"
|
||||||
gem "acts-as-taggable-on", "2.3.1"
|
gem "acts-as-taggable-on", "2.3.1"
|
||||||
|
|
||||||
# Decorators
|
# Decorators
|
||||||
gem "drapper"
|
gem "draper"
|
||||||
|
|
||||||
# Background jobs
|
# Background jobs
|
||||||
gem "resque", "~> 1.20.0"
|
gem "resque", "~> 1.20.0"
|
||||||
|
@ -80,10 +80,6 @@ gem 'settingslogic'
|
||||||
gem "foreman"
|
gem "foreman"
|
||||||
gem "git"
|
gem "git"
|
||||||
|
|
||||||
# Unused
|
|
||||||
gem 'tabs_on_rails'
|
|
||||||
gem "acts_as_list"
|
|
||||||
|
|
||||||
group :assets do
|
group :assets do
|
||||||
gem "sass-rails", "3.2.5"
|
gem "sass-rails", "3.2.5"
|
||||||
gem "coffee-rails", "3.2.2"
|
gem "coffee-rails", "3.2.2"
|
||||||
|
@ -95,12 +91,11 @@ group :assets do
|
||||||
gem "jquery-ui-rails", "0.5.0"
|
gem "jquery-ui-rails", "0.5.0"
|
||||||
gem "modernizr", "2.5.3"
|
gem "modernizr", "2.5.3"
|
||||||
gem "raphael-rails", "1.5.2"
|
gem "raphael-rails", "1.5.2"
|
||||||
gem 'bootstrap-sass', "2.0.3.1"
|
gem 'bootstrap-sass', "2.0.4"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem "letter_opener"
|
gem "letter_opener"
|
||||||
gem "rails-footnotes"
|
|
||||||
gem "annotate", :git => "https://github.com/ctran/annotate_models.git"
|
gem "annotate", :git => "https://github.com/ctran/annotate_models.git"
|
||||||
gem 'rack-mini-profiler'
|
gem 'rack-mini-profiler'
|
||||||
end
|
end
|
||||||
|
@ -109,6 +104,7 @@ group :development, :test do
|
||||||
gem "rspec-rails"
|
gem "rspec-rails"
|
||||||
gem "capybara"
|
gem "capybara"
|
||||||
gem "capybara-webkit"
|
gem "capybara-webkit"
|
||||||
|
gem "headless"
|
||||||
gem "autotest"
|
gem "autotest"
|
||||||
gem "autotest-rails"
|
gem "autotest-rails"
|
||||||
gem "pry"
|
gem "pry"
|
||||||
|
@ -119,11 +115,13 @@ end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'cucumber-rails', :require => false
|
gem 'cucumber-rails', :require => false
|
||||||
gem 'minitest', ">= 2.10"
|
|
||||||
gem "turn", :require => false
|
|
||||||
gem "simplecov", :require => false
|
gem "simplecov", :require => false
|
||||||
gem "shoulda-matchers"
|
gem "shoulda-matchers"
|
||||||
gem 'email_spec'
|
gem 'email_spec'
|
||||||
gem 'resque_spec'
|
gem 'resque_spec'
|
||||||
gem "webmock"
|
gem "webmock"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
group :production do
|
||||||
|
gem "gitlab_meta", '2.8'
|
||||||
|
end
|
||||||
|
|
27
Gemfile.lock
27
Gemfile.lock
|
@ -98,9 +98,7 @@ GEM
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
acts-as-taggable-on (2.3.1)
|
acts-as-taggable-on (2.3.1)
|
||||||
rails (~> 3.0)
|
rails (~> 3.0)
|
||||||
acts_as_list (0.1.6)
|
|
||||||
addressable (2.2.8)
|
addressable (2.2.8)
|
||||||
ansi (1.4.2)
|
|
||||||
arel (3.0.2)
|
arel (3.0.2)
|
||||||
autotest (4.4.6)
|
autotest (4.4.6)
|
||||||
ZenTest (>= 4.4.1)
|
ZenTest (>= 4.4.1)
|
||||||
|
@ -109,7 +107,7 @@ GEM
|
||||||
awesome_print (1.0.2)
|
awesome_print (1.0.2)
|
||||||
bcrypt-ruby (3.0.1)
|
bcrypt-ruby (3.0.1)
|
||||||
blankslate (2.1.2.4)
|
blankslate (2.1.2.4)
|
||||||
bootstrap-sass (2.0.3.1)
|
bootstrap-sass (2.0.4.0)
|
||||||
builder (3.0.0)
|
builder (3.0.0)
|
||||||
capybara (1.1.2)
|
capybara (1.1.2)
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
|
@ -157,7 +155,9 @@ GEM
|
||||||
railties (~> 3.1)
|
railties (~> 3.1)
|
||||||
warden (~> 1.2.1)
|
warden (~> 1.2.1)
|
||||||
diff-lcs (1.1.3)
|
diff-lcs (1.1.3)
|
||||||
drapper (0.8.4)
|
draper (0.17.0)
|
||||||
|
actionpack (~> 3.2)
|
||||||
|
activesupport (~> 3.2)
|
||||||
email_spec (1.2.1)
|
email_spec (1.2.1)
|
||||||
mail (~> 2.2)
|
mail (~> 2.2)
|
||||||
rspec (~> 2.0)
|
rspec (~> 2.0)
|
||||||
|
@ -175,6 +175,7 @@ GEM
|
||||||
gherkin (2.11.0)
|
gherkin (2.11.0)
|
||||||
json (>= 1.4.6)
|
json (>= 1.4.6)
|
||||||
git (1.2.5)
|
git (1.2.5)
|
||||||
|
gitlab_meta (2.8)
|
||||||
grape (0.2.1)
|
grape (0.2.1)
|
||||||
hashie (~> 1.2)
|
hashie (~> 1.2)
|
||||||
multi_json
|
multi_json
|
||||||
|
@ -189,6 +190,7 @@ GEM
|
||||||
railties (~> 3.0)
|
railties (~> 3.0)
|
||||||
hashery (1.4.0)
|
hashery (1.4.0)
|
||||||
hashie (1.2.0)
|
hashie (1.2.0)
|
||||||
|
headless (0.3.1)
|
||||||
hike (1.2.1)
|
hike (1.2.1)
|
||||||
httparty (0.8.3)
|
httparty (0.8.3)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
|
@ -223,7 +225,6 @@ GEM
|
||||||
treetop (~> 1.4.8)
|
treetop (~> 1.4.8)
|
||||||
method_source (0.7.1)
|
method_source (0.7.1)
|
||||||
mime-types (1.19)
|
mime-types (1.19)
|
||||||
minitest (3.1.0)
|
|
||||||
modernizr (2.5.3)
|
modernizr (2.5.3)
|
||||||
sprockets (~> 2.0)
|
sprockets (~> 2.0)
|
||||||
multi_json (1.3.6)
|
multi_json (1.3.6)
|
||||||
|
@ -286,8 +287,6 @@ GEM
|
||||||
activesupport (= 3.2.8)
|
activesupport (= 3.2.8)
|
||||||
bundler (~> 1.0)
|
bundler (~> 1.0)
|
||||||
railties (= 3.2.8)
|
railties (= 3.2.8)
|
||||||
rails-footnotes (3.7.8)
|
|
||||||
rails (>= 3.0.0)
|
|
||||||
railties (3.2.8)
|
railties (3.2.8)
|
||||||
actionpack (= 3.2.8)
|
actionpack (= 3.2.8)
|
||||||
activesupport (= 3.2.8)
|
activesupport (= 3.2.8)
|
||||||
|
@ -366,7 +365,6 @@ GEM
|
||||||
tilt (~> 1.1, != 1.3.0)
|
tilt (~> 1.1, != 1.3.0)
|
||||||
sqlite3 (1.3.6)
|
sqlite3 (1.3.6)
|
||||||
stamp (0.1.6)
|
stamp (0.1.6)
|
||||||
tabs_on_rails (2.1.1)
|
|
||||||
therubyracer (0.10.1)
|
therubyracer (0.10.1)
|
||||||
libv8 (~> 3.3.10)
|
libv8 (~> 3.3.10)
|
||||||
thin (1.3.1)
|
thin (1.3.1)
|
||||||
|
@ -378,8 +376,6 @@ GEM
|
||||||
treetop (1.4.10)
|
treetop (1.4.10)
|
||||||
polyglot
|
polyglot
|
||||||
polyglot (>= 0.3.1)
|
polyglot (>= 0.3.1)
|
||||||
turn (0.9.5)
|
|
||||||
ansi
|
|
||||||
tzinfo (0.3.33)
|
tzinfo (0.3.33)
|
||||||
uglifier (1.0.3)
|
uglifier (1.0.3)
|
||||||
execjs (>= 0.3.0)
|
execjs (>= 0.3.0)
|
||||||
|
@ -403,12 +399,11 @@ PLATFORMS
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
acts-as-taggable-on (= 2.3.1)
|
acts-as-taggable-on (= 2.3.1)
|
||||||
acts_as_list
|
|
||||||
annotate!
|
annotate!
|
||||||
autotest
|
autotest
|
||||||
autotest-rails
|
autotest-rails
|
||||||
awesome_print
|
awesome_print
|
||||||
bootstrap-sass (= 2.0.3.1)
|
bootstrap-sass (= 2.0.4)
|
||||||
capybara
|
capybara
|
||||||
capybara-webkit
|
capybara-webkit
|
||||||
carrierwave
|
carrierwave
|
||||||
|
@ -419,16 +414,18 @@ DEPENDENCIES
|
||||||
cucumber-rails
|
cucumber-rails
|
||||||
database_cleaner
|
database_cleaner
|
||||||
devise (~> 2.1.0)
|
devise (~> 2.1.0)
|
||||||
drapper
|
draper
|
||||||
email_spec
|
email_spec
|
||||||
ffaker
|
ffaker
|
||||||
foreman
|
foreman
|
||||||
git
|
git
|
||||||
|
gitlab_meta (= 2.8)
|
||||||
gitolite!
|
gitolite!
|
||||||
grack!
|
grack!
|
||||||
grape (~> 0.2.1)
|
grape (~> 0.2.1)
|
||||||
grit!
|
grit!
|
||||||
haml-rails
|
haml-rails
|
||||||
|
headless
|
||||||
httparty
|
httparty
|
||||||
jquery-rails (= 2.0.2)
|
jquery-rails (= 2.0.2)
|
||||||
jquery-ui-rails (= 0.5.0)
|
jquery-ui-rails (= 0.5.0)
|
||||||
|
@ -436,7 +433,6 @@ DEPENDENCIES
|
||||||
launchy
|
launchy
|
||||||
letter_opener
|
letter_opener
|
||||||
linguist (~> 1.0.0)!
|
linguist (~> 1.0.0)!
|
||||||
minitest (>= 2.10)
|
|
||||||
modernizr (= 2.5.3)
|
modernizr (= 2.5.3)
|
||||||
mysql2
|
mysql2
|
||||||
omniauth
|
omniauth
|
||||||
|
@ -448,7 +444,6 @@ DEPENDENCIES
|
||||||
pygments.rb!
|
pygments.rb!
|
||||||
rack-mini-profiler
|
rack-mini-profiler
|
||||||
rails (= 3.2.8)
|
rails (= 3.2.8)
|
||||||
rails-footnotes
|
|
||||||
raphael-rails (= 1.5.2)
|
raphael-rails (= 1.5.2)
|
||||||
redcarpet (~> 2.1.1)
|
redcarpet (~> 2.1.1)
|
||||||
resque (~> 1.20.0)
|
resque (~> 1.20.0)
|
||||||
|
@ -463,10 +458,8 @@ DEPENDENCIES
|
||||||
six
|
six
|
||||||
sqlite3
|
sqlite3
|
||||||
stamp
|
stamp
|
||||||
tabs_on_rails
|
|
||||||
therubyracer
|
therubyracer
|
||||||
thin
|
thin
|
||||||
turn
|
|
||||||
uglifier (= 1.0.3)
|
uglifier (= 1.0.3)
|
||||||
unicorn
|
unicorn
|
||||||
webmock
|
webmock
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
2.8.0pre
|
2.8.2
|
||||||
|
|
BIN
app/assets/fonts/korolev-medium-compressed.otf
Normal file
BIN
app/assets/fonts/korolev-medium-compressed.otf
Normal file
Binary file not shown.
BIN
app/assets/images/logo_dark.png
Normal file
BIN
app/assets/images/logo_dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
BIN
app/assets/images/logo_white.png
Normal file
BIN
app/assets/images/logo_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
|
@ -7,8 +7,6 @@
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery.ui.all
|
//= require jquery.ui.all
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require jquery.ui.selectmenu
|
|
||||||
//= require jquery.tagify
|
|
||||||
//= require jquery.cookie
|
//= require jquery.cookie
|
||||||
//= require jquery.endless-scroll
|
//= require jquery.endless-scroll
|
||||||
//= require jquery.highlight
|
//= require jquery.highlight
|
||||||
|
@ -74,7 +72,7 @@ $(document).ready(function(){
|
||||||
* Note markdown preview
|
* Note markdown preview
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
$('#preview-link').on('click', function(e) {
|
$(document).on('click', '#preview-link', function(e) {
|
||||||
$('#preview-note').text('Loading...');
|
$('#preview-note').text('Loading...');
|
||||||
|
|
||||||
var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
|
var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
|
||||||
|
|
|
@ -112,6 +112,7 @@ var MergeRequest = {
|
||||||
already_cannot_be_merged:
|
already_cannot_be_merged:
|
||||||
function(){
|
function(){
|
||||||
$(".automerge_widget").hide();
|
$(".automerge_widget").hide();
|
||||||
|
$(".merge_in_progress").hide();
|
||||||
$(".automerge_widget.already_cannot_be_merged").show();
|
$(".automerge_widget.already_cannot_be_merged").show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
||||||
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
||||||
*= require jquery.ui.all
|
*= require jquery.ui.all
|
||||||
*= require jquery-ui/jquery.ui.selectmenu
|
*= require jquery.ui.aristo
|
||||||
*= require jquery-ui/jquery.tagify
|
|
||||||
*= require chosen
|
*= require chosen
|
||||||
*= require_self
|
*= require_self
|
||||||
*= require main
|
*= require main
|
||||||
|
|
|
@ -735,3 +735,11 @@ li.note {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error_message {
|
||||||
|
@extend .cred;
|
||||||
|
border-bottom: 1px solid #D21;
|
||||||
|
padding-bottom:20px;
|
||||||
|
text-align:center;
|
||||||
|
margin-bottom:10px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
body {
|
body {
|
||||||
margin-bottom:20px;
|
margin-bottom:20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
background: #333;
|
||||||
|
color:#f5f5f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
outline: none;
|
outline: none;
|
||||||
color: $link_color;
|
color: $link_color;
|
||||||
|
@ -325,16 +335,20 @@ img.avatar {
|
||||||
float:left;
|
float:left;
|
||||||
margin-right:15px;
|
margin-right:15px;
|
||||||
width:40px;
|
width:40px;
|
||||||
border:2px solid #ddd;
|
border:1px solid #ddd;
|
||||||
|
padding:1px;
|
||||||
|
|
||||||
&.s16 {
|
&.s16 {
|
||||||
width:16px;
|
width:16px;
|
||||||
|
height:16px;
|
||||||
}
|
}
|
||||||
&.s24 {
|
&.s24 {
|
||||||
width:24px;
|
width:24px;
|
||||||
|
height:24px;
|
||||||
}
|
}
|
||||||
&.s32 {
|
&.s32 {
|
||||||
width:32px;
|
width:32px;
|
||||||
|
height:32px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/**
|
|
||||||
* JQUERY UI datepicker
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
.ui-datepicker {
|
|
||||||
border-color:#eee;
|
|
||||||
padding:20px;
|
|
||||||
|
|
||||||
.ui-state-default {
|
|
||||||
background:#f1f1f1;
|
|
||||||
padding:5px;
|
|
||||||
}
|
|
||||||
.ui-state-active {
|
|
||||||
background:#fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JQUERY UI progressbar
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
.ui-progressbar {
|
|
||||||
border:1px solid #ddd;
|
|
||||||
height:6px;
|
|
||||||
margin:0;
|
|
||||||
padding:0;
|
|
||||||
|
|
||||||
.ui-progressbar-value {
|
|
||||||
background-color: #62C462;//$blue_link;
|
|
||||||
margin:0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ $blue_link: #2fa0bb;
|
||||||
$style_color: #474D57;
|
$style_color: #474D57;
|
||||||
$hover: #FDF5D9;
|
$hover: #FDF5D9;
|
||||||
|
|
||||||
|
/** GITLAB Fonts **/
|
||||||
|
@font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); }
|
||||||
|
|
||||||
/** MIXINS **/
|
/** MIXINS **/
|
||||||
@mixin shade {
|
@mixin shade {
|
||||||
|
@ -165,9 +167,3 @@ $hover: #FDF5D9;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@import "highlight/dark.scss";
|
@import "highlight/dark.scss";
|
||||||
|
|
||||||
/**
|
|
||||||
* JQUERY UI ext
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@import "jquery_ui.scss";
|
|
||||||
|
|
|
@ -26,23 +26,25 @@ header {
|
||||||
float:left;
|
float:left;
|
||||||
position:relative;
|
position:relative;
|
||||||
top:-5px;
|
top:-5px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
float:left;
|
float:left;
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
text-indent:-9999px;
|
padding-top: 5px;
|
||||||
width:102px;
|
width:102px;
|
||||||
background: url('logo_text.png') no-repeat 0px -3px;
|
background: url('logo_dark.png') no-repeat 0px -3px;
|
||||||
float:left;
|
float:left;
|
||||||
margin-left:5px;
|
margin-left:5px;
|
||||||
font-size:20px;
|
font-size:36px;
|
||||||
line-height:36px;
|
line-height:36px;
|
||||||
font-weight:bold;
|
font-weight:normal;
|
||||||
color:#aaa;
|
color:$style_color;
|
||||||
text-shadow: 0 1px 1px #FFF;
|
text-shadow: 0 1px 1px #FFF;
|
||||||
padding-left:50px;
|
padding-left:50px;
|
||||||
|
height:40px;
|
||||||
|
font-family: 'Korolev', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.separator {
|
.separator {
|
||||||
margin-left:20px;
|
margin-left:20px;
|
||||||
|
@ -68,14 +70,16 @@ header {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
.project_name {
|
.project_name {
|
||||||
|
position:relative;
|
||||||
float:left;
|
float:left;
|
||||||
margin:0;
|
margin:0;
|
||||||
margin-right:30px;
|
margin-right:30px;
|
||||||
font-size:24px;
|
font-size:36px;
|
||||||
line-height:36px;
|
line-height:36px;
|
||||||
font-weight:500;
|
font-weight:normal;
|
||||||
color:$style_color;
|
color:$style_color;
|
||||||
text-shadow: 0 1px 1px #FFF;
|
text-shadow: 0 1px 1px #FFF;
|
||||||
|
font-family: 'Korolev', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fbtn {
|
.fbtn {
|
||||||
|
|
|
@ -27,6 +27,7 @@ body.login-page{
|
||||||
-moz-border-radius-topright: 5px;
|
-moz-border-radius-topright: 5px;
|
||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
border-top-right-radius: 5px;
|
border-top-right-radius: 5px;
|
||||||
|
margin-bottom:0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-box input.text.bottom{
|
.login-box input.text.bottom{
|
||||||
|
|
|
@ -94,3 +94,8 @@ li.merge_request {
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.merge_in_progress {
|
||||||
|
@extend .padded;
|
||||||
|
@extend .append-bottom-10;
|
||||||
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
p { color:$style_color; }
|
p { color:$style_color; }
|
||||||
.note-author { color: $style_color;}
|
.note-author { color: $style_color;}
|
||||||
|
|
||||||
.note-title { margin-left:50px; padding-top: 5px;}
|
.note-title { margin-left:45px; padding-top: 5px;}
|
||||||
.avatar {
|
.avatar {
|
||||||
margin-top:3px;
|
margin-top:3px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
.projects {
|
.projects {
|
||||||
@extend .row;
|
@extend .row;
|
||||||
.activities {
|
.activities {
|
||||||
}
|
}
|
||||||
|
|
||||||
.side {
|
.side {
|
||||||
@extend .span4;
|
@extend .span4;
|
||||||
@extend .right;
|
@extend .right;
|
||||||
|
|
||||||
.projects_box {
|
.projects_box {
|
||||||
h5 {
|
h5 {
|
||||||
color:$style_color;
|
color:$style_color;
|
||||||
font-size:16px;
|
font-size:16px;
|
||||||
text-shadow: 0 1px 1px #fff;
|
text-shadow: 0 1px 1px #fff;
|
||||||
|
padding: 2px 10px;
|
||||||
}
|
}
|
||||||
@extend .leftbar;
|
@extend .leftbar;
|
||||||
@extend .ui-box;
|
@extend .ui-box;
|
||||||
|
@ -19,21 +20,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.new_project,
|
.new_project,
|
||||||
.edit_project {
|
.edit_project {
|
||||||
.project_name_holder {
|
.project_name_holder {
|
||||||
input,
|
input,
|
||||||
label {
|
label {
|
||||||
font-size:16px;
|
font-size:16px;
|
||||||
line-height:20px;
|
line-height:20px;
|
||||||
padding:8px;
|
padding:8px;
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
color:#888;
|
color:#888;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
padding:6px;
|
padding:6px;
|
||||||
margin-left:10px;
|
margin-left:10px;
|
||||||
|
margin-bottom:8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,36 @@
|
||||||
color: $blue_link;
|
color: $blue_link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
.fbtn {
|
||||||
|
.btn {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
background-image: -webkit-gradient(linear,left top,left bottom,from(#F8F8F8),to(#ECECEC));
|
||||||
|
background-image: -webkit-linear-gradient(top,#F8F8F8,#ECECEC);
|
||||||
|
background-image: -moz-linear-gradient(top,#F8F8F8,#ECECEC);
|
||||||
|
background-image: -ms-linear-gradient(top,#F8F8F8,#ECECEC);
|
||||||
|
background-image: -o-linear-gradient(top,#F8F8F8,#ECECEC);
|
||||||
|
background-image: linear-gradient(top,#F8F8F8,#ECECEC);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f8f8f8',EndColorStr='#ececec');
|
||||||
|
border-color: #C6C6C6;
|
||||||
|
margin-left:7px;
|
||||||
|
@include border-radius(3px);
|
||||||
|
box-shadow:none;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
.search-input {
|
||||||
|
@include border-radius(3px);
|
||||||
|
border-color: #C6C6C6;
|
||||||
|
box-shadow:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pic {
|
||||||
|
img {
|
||||||
|
@include border-radius(3px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
.fbtn {
|
.fbtn {
|
||||||
.btn {
|
.btn {
|
||||||
|
i {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
margin-left:8px;
|
margin-left:8px;
|
||||||
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595D63), to(#31363E));
|
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595D63), to(#31363E));
|
||||||
background-image: -webkit-linear-gradient(#595D63 6.6%, #31363E);
|
background-image: -webkit-linear-gradient(#595D63 6.6%, #31363E);
|
||||||
|
@ -32,6 +36,10 @@
|
||||||
background-image: -moz-linear-gradient(#595D63 6.6%, #202227);
|
background-image: -moz-linear-gradient(#595D63 6.6%, #202227);
|
||||||
background-image: -o-linear-gradient(#595D63 6.6%, #202227);
|
background-image: -o-linear-gradient(#595D63 6.6%, #202227);
|
||||||
background-position:0 0;
|
background-position:0 0;
|
||||||
|
color:#fff;
|
||||||
|
i {
|
||||||
|
@extend .icon-white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
border: 1px solid #31363E;
|
border: 1px solid #31363E;
|
||||||
|
@ -59,14 +67,9 @@
|
||||||
.app_logo {
|
.app_logo {
|
||||||
a {
|
a {
|
||||||
h1 {
|
h1 {
|
||||||
background: url('images.png') no-repeat -3px -6px;
|
background: url('logo_white.png') no-repeat 0px -3px;
|
||||||
width: 65px;
|
color:#fff;
|
||||||
height: 26px;
|
text-shadow: 0 1px 1px #111;
|
||||||
margin: 6px 0;
|
|
||||||
padding: 0;
|
|
||||||
float: left;
|
|
||||||
text-indent: -1000em;
|
|
||||||
float:left;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.separator {
|
.separator {
|
||||||
|
@ -75,7 +78,6 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
.project_name {
|
.project_name {
|
||||||
line-height:38px;
|
|
||||||
color:#fff;
|
color:#fff;
|
||||||
text-shadow: 0 1px 1px #111;
|
text-shadow: 0 1px 1px #111;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,26 +37,20 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
.app_logo {
|
.app_logo {
|
||||||
|
width:160px;
|
||||||
a {
|
a {
|
||||||
h1 {
|
h1 {
|
||||||
opacity: 0.7;
|
background: none;
|
||||||
background: url('images.png') no-repeat -3px -6px;
|
color:#DDD;
|
||||||
width: 65px;
|
font-size:30px;
|
||||||
height: 26px;
|
text-shadow: 0 1px 1px #111;
|
||||||
margin: 6px 0;
|
padding-left: 0;
|
||||||
padding: 0;
|
|
||||||
float: left;
|
|
||||||
text-indent: -1000em;
|
|
||||||
float:left;
|
|
||||||
&:hover {
|
|
||||||
opacity: 1.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.separator {
|
.separator {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
margin: 0 9px;
|
margin: 0 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #222;
|
background: #222;
|
||||||
border-left: 1px solid #333;
|
border-left: 1px solid #333;
|
||||||
|
@ -66,7 +60,6 @@
|
||||||
.fbtn {
|
.fbtn {
|
||||||
.btn {
|
.btn {
|
||||||
i {
|
i {
|
||||||
@extend .icon-white;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
}
|
}
|
||||||
|
@ -77,10 +70,14 @@
|
||||||
color:#ccc;
|
color:#ccc;
|
||||||
&:hover {
|
&:hover {
|
||||||
color:#fff;
|
color:#fff;
|
||||||
|
i {
|
||||||
|
@extend .icon-white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow:none;
|
box-shadow:none;
|
||||||
text-shadow: 0 -1px 0 #000000;
|
text-shadow: 0 -1px 0 #000000;
|
||||||
|
border-left: 1px solid #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +110,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
.project_name {
|
.project_name {
|
||||||
line-height:34px;
|
line-height:36px;
|
||||||
font-size:22px;
|
font-size:30px;
|
||||||
color:#fff;
|
color:#DDD;
|
||||||
text-shadow: 0 1px 1px #111;
|
text-shadow: 0 1px 1px #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
app/controllers/labels_controller.rb
Normal file
25
app/controllers/labels_controller.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class LabelsController < ApplicationController
|
||||||
|
before_filter :authenticate_user!
|
||||||
|
before_filter :project
|
||||||
|
before_filter :module_enabled
|
||||||
|
|
||||||
|
layout "project"
|
||||||
|
|
||||||
|
# Authorize
|
||||||
|
before_filter :add_project_abilities
|
||||||
|
|
||||||
|
# Allow read any issue
|
||||||
|
before_filter :authorize_read_issue!
|
||||||
|
|
||||||
|
respond_to :js, :html
|
||||||
|
|
||||||
|
def index
|
||||||
|
@labels = Issue.tag_counts_on(:labels)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def module_enabled
|
||||||
|
return render_404 unless @project.issues_enabled
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,8 +12,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
|
||||||
def ldap
|
def ldap
|
||||||
# We only find ourselves here if the authentication to LDAP was successful.
|
# We only find ourselves here if the authentication to LDAP was successful.
|
||||||
info = request.env["omniauth.auth"]["info"]
|
@user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user)
|
||||||
@user = User.find_for_ldap_auth(info)
|
|
||||||
if @user.persisted?
|
if @user.persisted?
|
||||||
@user.remember_me = true
|
@user.remember_me = true
|
||||||
end
|
end
|
||||||
|
@ -39,7 +38,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
current_user.save
|
current_user.save
|
||||||
redirect_to profile_path
|
redirect_to profile_path
|
||||||
else
|
else
|
||||||
@user = User.find_by_provider_and_uid(provider, uid)
|
@user = User.find_by_provider_and_extern_uid(provider, uid)
|
||||||
|
|
||||||
if @user
|
if @user
|
||||||
sign_in_and_redirect @user
|
sign_in_and_redirect @user
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require File.join(Rails.root, 'lib', 'graph_commit')
|
require Rails.root.join('lib', 'gitlab', 'graph_commit')
|
||||||
|
|
||||||
class ProjectsController < ApplicationController
|
class ProjectsController < ApplicationController
|
||||||
before_filter :project, except: [:index, :new, :create]
|
before_filter :project, except: [:index, :new, :create]
|
||||||
|
@ -78,7 +78,7 @@ class ProjectsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def graph
|
def graph
|
||||||
@days_json, @commits_json = GraphCommit.to_graph(project)
|
@days_json, @commits_json = Gitlab::GraphCommit.to_graph(project)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -9,6 +9,7 @@ class TeamMembersController < ApplicationController
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@team_member = project.users_projects.find(params[:id])
|
@team_member = project.users_projects.find(params[:id])
|
||||||
|
@events = @team_member.user.recent_events.where(:project_id => @project.id).limit(7)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class ApplicationDecorator < Drapper::Base
|
class ApplicationDecorator < Draper::Base
|
||||||
# Lazy Helpers
|
# Lazy Helpers
|
||||||
# PRO: Call Rails helpers without the h. proxy
|
# PRO: Call Rails helpers without the h. proxy
|
||||||
# ex: number_to_currency(model.price)
|
# ex: number_to_currency(model.price)
|
||||||
|
|
|
@ -2,10 +2,13 @@ require 'digest/md5'
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
|
||||||
def gravatar_icon(user_email = '', size = 40)
|
def gravatar_icon(user_email = '', size = 40)
|
||||||
return unless user_email
|
if Gitlab.config.disable_gravatar? || user_email.blank?
|
||||||
gravatar_host = request.ssl? ? "https://secure.gravatar.com" : "http://www.gravatar.com"
|
'no_avatar.png'
|
||||||
user_email.strip!
|
else
|
||||||
"#{gravatar_host}/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=identicon"
|
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
|
end
|
||||||
|
|
||||||
def request_protocol
|
def request_protocol
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
module GitlabMarkdownHelper
|
module GitlabMarkdownHelper
|
||||||
|
# Replaces references (i.e. @abc, #123, !456, ...) in the text with links to
|
||||||
|
# the appropriate items in Gitlab.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# see Gitlab::Markdown for details on the supported syntax
|
||||||
def gfm(text, html_options = {})
|
def gfm(text, html_options = {})
|
||||||
return text if text.nil?
|
return text if text.nil?
|
||||||
return text if @project.nil?
|
return text if @project.nil?
|
||||||
|
|
||||||
# Extract pre blocks
|
# Extract pre blocks so they are not altered
|
||||||
# from http://github.github.com/github-flavored-markdown/
|
# from http://github.github.com/github-flavored-markdown/
|
||||||
extractions = {}
|
extractions = {}
|
||||||
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
|
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
|
||||||
|
@ -25,7 +34,15 @@ module GitlabMarkdownHelper
|
||||||
text.html_safe
|
text.html_safe
|
||||||
end
|
end
|
||||||
|
|
||||||
# circumvents nesting links, which will behave bad in browsers
|
# 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 = {})
|
def link_to_gfm(body, url, html_options = {})
|
||||||
gfm_body = gfm(body, html_options)
|
gfm_body = gfm(body, html_options)
|
||||||
|
|
||||||
|
|
|
@ -12,74 +12,102 @@ class Notify < ActionMailer::Base
|
||||||
def new_user_email(user_id, password)
|
def new_user_email(user_id, password)
|
||||||
@user = User.find(user_id)
|
@user = User.find(user_id)
|
||||||
@password = password
|
@password = password
|
||||||
mail(to: @user.email, subject: "gitlab | Account was created for you")
|
mail(to: @user.email, subject: subject("Account was created for you"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_issue_email(issue_id)
|
def new_issue_email(issue_id)
|
||||||
@issue = Issue.find(issue_id)
|
@issue = Issue.find(issue_id)
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
mail(to: @issue.assignee_email, subject: "gitlab | new issue ##{@issue.id} | #{@issue.title} | #{@project.name}")
|
mail(to: @issue.assignee_email, subject: subject("new issue ##{@issue.id}", @issue.title))
|
||||||
end
|
end
|
||||||
|
|
||||||
def note_wall_email(recipient_id, note_id)
|
def note_wall_email(recipient_id, note_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@note = Note.find(note_id)
|
@note = Note.find(note_id)
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
mail(to: recipient.email, subject: "gitlab | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject)
|
||||||
end
|
end
|
||||||
|
|
||||||
def note_commit_email(recipient_id, note_id)
|
def note_commit_email(recipient_id, note_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@note = Note.find(note_id)
|
@note = Note.find(note_id)
|
||||||
@commit = @note.target
|
@commit = @note.target
|
||||||
@commit = CommitDecorator.decorate(@commit)
|
@commit = CommitDecorator.decorate(@commit)
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
mail(to: recipient.email, subject: "gitlab | note for commit #{@commit.short_id} | #{@commit.title} | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
|
||||||
end
|
end
|
||||||
|
|
||||||
def note_merge_request_email(recipient_id, note_id)
|
def note_merge_request_email(recipient_id, note_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@note = Note.find(note_id)
|
@note = Note.find(note_id)
|
||||||
@merge_request = @note.noteable
|
@merge_request = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
mail(to: recipient.email, subject: "gitlab | note for merge request !#{@merge_request.id} | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("note for merge request !#{@merge_request.id}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def note_issue_email(recipient_id, note_id)
|
def note_issue_email(recipient_id, note_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@note = Note.find(note_id)
|
@note = Note.find(note_id)
|
||||||
@issue = @note.noteable
|
@issue = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
mail(to: recipient.email, subject: "gitlab | note for issue ##{@issue.id} | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.id}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def note_wiki_email(recipient_id, note_id)
|
def note_wiki_email(recipient_id, note_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@note = Note.find(note_id)
|
@note = Note.find(note_id)
|
||||||
@wiki = @note.noteable
|
@wiki = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
mail(to: recipient.email, subject: "gitlab | note for wiki | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("note for wiki"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_merge_request_email(merge_request_id)
|
def new_merge_request_email(merge_request_id)
|
||||||
@merge_request = MergeRequest.find(merge_request_id)
|
@merge_request = MergeRequest.find(merge_request_id)
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
mail(to: @merge_request.assignee_email, subject: "gitlab | new merge request !#{@merge_request.id} | #{@merge_request.title} | #{@project.name}")
|
mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title))
|
||||||
end
|
end
|
||||||
|
|
||||||
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
|
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@merge_request = MergeRequest.find(merge_request_id)
|
@merge_request = MergeRequest.find(merge_request_id)
|
||||||
@previous_assignee ||= User.find(previous_assignee_id)
|
@previous_assignee ||= User.find(previous_assignee_id)
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
mail(to: recipient.email, subject: "gitlab | changed merge request !#{@merge_request.id} | #{@merge_request.title} | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title))
|
||||||
end
|
end
|
||||||
|
|
||||||
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
|
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
|
||||||
recipient = User.find(recipient_id)
|
|
||||||
@issue = Issue.find(issue_id)
|
@issue = Issue.find(issue_id)
|
||||||
@previous_assignee ||= User.find(previous_assignee_id)
|
@previous_assignee ||= User.find(previous_assignee_id)
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
mail(to: recipient.email, subject: "gitlab | changed issue ##{@issue.id} | #{@issue.title} | #{@project.name}")
|
mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title))
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Look up a User by their ID and return their email address
|
||||||
|
#
|
||||||
|
# recipient_id - User ID
|
||||||
|
#
|
||||||
|
# Returns a String containing the User's email address.
|
||||||
|
def recipient(recipient_id)
|
||||||
|
if recipient = User.find(recipient_id)
|
||||||
|
recipient.email
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Formats arguments into a String suitable for use as an email subject
|
||||||
|
#
|
||||||
|
# extra - Extra Strings to be inserted into the subject
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# >> subject('Lorem ipsum')
|
||||||
|
# => "gitlab | Lorem ipsum"
|
||||||
|
#
|
||||||
|
# # Automatically inserts Project name when @project is set
|
||||||
|
# >> @project = Project.last
|
||||||
|
# => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...>
|
||||||
|
# >> subject('Lorem ipsum')
|
||||||
|
# => "gitlab | Lorem ipsum | Ruby on Rails"
|
||||||
|
#
|
||||||
|
# # Accepts multiple arguments
|
||||||
|
# >> subject('Lorem ipsum', 'Dolor sit amet')
|
||||||
|
# => "gitlab | Lorem ipsum | Dolor sit amet"
|
||||||
|
def subject(*extra)
|
||||||
|
"gitlab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,8 +9,6 @@ class Issue < ActiveRecord::Base
|
||||||
validates :description,
|
validates :description,
|
||||||
length: { within: 0..2000 }
|
length: { within: 0..2000 }
|
||||||
|
|
||||||
acts_as_list
|
|
||||||
|
|
||||||
def self.open_for(user)
|
def self.open_for(user)
|
||||||
opened.assigned(user)
|
opened.assigned(user)
|
||||||
end
|
end
|
||||||
|
|
|
@ -88,8 +88,11 @@ class MergeRequest < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def unmerged_diffs
|
def unmerged_diffs
|
||||||
commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)}
|
# Only show what is new in the source branch compared to the target branch, not the other way around.
|
||||||
diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue []
|
# The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
|
||||||
|
# From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
|
||||||
|
common_commit = project.repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip
|
||||||
|
diffs = project.repo.diff(common_commit, source_branch)
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_commit
|
def last_commit
|
||||||
|
|
|
@ -2,7 +2,7 @@ require "grit"
|
||||||
|
|
||||||
class Project < ActiveRecord::Base
|
class Project < ActiveRecord::Base
|
||||||
include Repository
|
include Repository
|
||||||
include ProjectPush
|
include PushObserver
|
||||||
include Authority
|
include Authority
|
||||||
include Team
|
include Team
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio,
|
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio,
|
||||||
:name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme,
|
:name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme,
|
||||||
:theme_id, :force_random_password
|
:theme_id, :force_random_password, :extern_uid, :provider
|
||||||
|
|
||||||
attr_accessor :force_random_password
|
attr_accessor :force_random_password
|
||||||
|
|
||||||
|
@ -54,6 +54,8 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
validates :bio, length: { within: 0..255 }
|
validates :bio, length: { within: 0..255 }
|
||||||
|
|
||||||
|
validates :extern_uid, :allow_blank => true, :uniqueness => {:scope => :provider}
|
||||||
|
|
||||||
before_save :ensure_authentication_token
|
before_save :ensure_authentication_token
|
||||||
alias_attribute :private_token, :authentication_token
|
alias_attribute :private_token, :authentication_token
|
||||||
|
|
||||||
|
@ -84,21 +86,31 @@ class User < ActiveRecord::Base
|
||||||
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
|
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_for_ldap_auth(omniauth_info)
|
def self.find_for_ldap_auth(auth, signed_in_resource=nil)
|
||||||
name = omniauth_info.name.force_encoding("utf-8")
|
uid = auth.info.uid
|
||||||
email = omniauth_info.email.downcase unless omniauth_info.email.nil?
|
provider = auth.provider
|
||||||
raise OmniAuth::Error, "LDAP accounts must provide an email address" if email.nil?
|
name = auth.info.name.force_encoding("utf-8")
|
||||||
|
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_email(email)
|
if @user = User.find_by_extern_uid_and_provider(uid, provider)
|
||||||
|
@user
|
||||||
|
# workaround for backward compatibility
|
||||||
|
elsif @user = User.find_by_email(email)
|
||||||
|
logger.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
|
||||||
|
@user.update_attributes(:extern_uid => uid, :provider => provider)
|
||||||
@user
|
@user
|
||||||
else
|
else
|
||||||
|
logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
|
||||||
password = Devise.friendly_token[0, 8].downcase
|
password = Devise.friendly_token[0, 8].downcase
|
||||||
@user = User.create(
|
@user = User.create(
|
||||||
name: name,
|
:extern_uid => uid,
|
||||||
email: email,
|
:provider => provider,
|
||||||
password: password,
|
:name => name,
|
||||||
password_confirmation: password,
|
:email => email,
|
||||||
projects_limit: Gitlab.config.default_projects_limit
|
:password => password,
|
||||||
|
:password_confirmation => password,
|
||||||
|
:projects_limit => Gitlab.config.default_projects_limit
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module ProjectPush
|
module PushObserver
|
||||||
def observe_push(oldrev, newrev, ref, user)
|
def observe_push(oldrev, newrev, ref, user)
|
||||||
data = post_receive_data(oldrev, newrev, ref, user)
|
data = post_receive_data(oldrev, newrev, ref, user)
|
||||||
|
|
|
@ -30,26 +30,10 @@ module Repository
|
||||||
Commit.commits_between(repo, from, to)
|
Commit.commits_between(repo, from, to)
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_hooks
|
|
||||||
%w(post-receive).each do |hook|
|
|
||||||
write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def satellite
|
def satellite
|
||||||
@satellite ||= Gitlab::Satellite.new(self)
|
@satellite ||= Gitlab::Satellite.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_hook(name, content)
|
|
||||||
hook_file = File.join(path_to_repo, 'hooks', name)
|
|
||||||
|
|
||||||
File.open(hook_file, 'w') do |f|
|
|
||||||
f.write(content)
|
|
||||||
end
|
|
||||||
|
|
||||||
File.chmod(0775, hook_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_post_receive_file?
|
def has_post_receive_file?
|
||||||
hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
|
hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
|
||||||
File.exists?(hook_file)
|
File.exists?(hook_file)
|
||||||
|
@ -73,8 +57,6 @@ module Repository
|
||||||
|
|
||||||
def update_repository
|
def update_repository
|
||||||
Gitlab::GitHost.system.update_project(path, self)
|
Gitlab::GitHost.system.update_project(path, self)
|
||||||
|
|
||||||
write_hooks if File.exists?(path_to_repo)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_repository
|
def destroy_repository
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
Read more about system hooks
|
Read more about system hooks
|
||||||
%strong #{link_to "here", help_system_hooks_path, class: "vlink"}
|
%strong #{link_to "here", help_system_hooks_path, class: "vlink"}
|
||||||
|
|
||||||
= form_for @hook, as: :hook, url: admin_hooks_path do |f|
|
= form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
|
||||||
-if @hook.errors.any?
|
-if @hook.errors.any?
|
||||||
.alert-message.block-message.error
|
.alert-message.block-message.error
|
||||||
- @hook.errors.full_messages.each do |msg|
|
- @hook.errors.full_messages.each do |msg|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
Projects
|
Projects
|
||||||
= link_to 'New Project', new_admin_project_path, class: "btn small right"
|
= link_to 'New Project', new_admin_project_path, class: "btn small right"
|
||||||
%br
|
%br
|
||||||
= form_tag admin_projects_path, method: :get do
|
= form_tag admin_projects_path, method: :get, class: 'form-inline' do
|
||||||
= text_field_tag :name, params[:name], class: "xlarge"
|
= text_field_tag :name, params[:name], class: "xlarge"
|
||||||
= submit_tag "Search", class: "btn submit primary"
|
= submit_tag "Search", class: "btn submit primary"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
= link_to 'New User', new_admin_user_path, class: "btn small right"
|
= link_to 'New User', new_admin_user_path, class: "btn small right"
|
||||||
%br
|
%br
|
||||||
|
|
||||||
= form_tag admin_users_path, method: :get do
|
= form_tag admin_users_path, method: :get, class: 'form-inline' do
|
||||||
= text_field_tag :name, params[:name], class: "xlarge"
|
= text_field_tag :name, params[:name], class: "xlarge"
|
||||||
= submit_tag "Search", class: "btn submit primary"
|
= submit_tag "Search", class: "btn submit primary"
|
||||||
%ul.nav.nav-pills
|
%ul.nav.nav-pills
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
%span.btn.disabled.grouped
|
%span.btn.disabled.grouped
|
||||||
%i.icon-comment
|
%i.icon-comment
|
||||||
= @notes_count
|
= @notes_count
|
||||||
= link_to patch_project_commit_path(@project, @commit.id), class: "btn small grouped" do
|
= link_to patch_project_commit_path(@project, @commit.id), class: "btn small grouped" do
|
||||||
%i.icon-download-alt
|
%i.icon-download-alt
|
||||||
Get Patch
|
Get Patch
|
||||||
= link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
|
= link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
|
||||||
%strong Browse Code »
|
%strong Browse Code »
|
||||||
%h3.commit-title.page_title
|
%h3.commit-title.page_title
|
||||||
= gfm @commit.title
|
= gfm @commit.title
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
- if @projects.any?
|
- if @projects.any?
|
||||||
.projects
|
.projects
|
||||||
.activities.span8
|
.activities.span8
|
||||||
- if current_user.require_ssh_key?
|
= render 'shared/no_ssh'
|
||||||
.alert.alert-error.padded
|
|
||||||
%span
|
|
||||||
You wont be able to pull/push project code unless you
|
|
||||||
%strong
|
|
||||||
= link_to new_key_path, class: "vlink" do
|
|
||||||
add new key
|
|
||||||
to your profile
|
|
||||||
- if @events.any?
|
- if @events.any?
|
||||||
.content_list= render @events
|
.content_list= render @events
|
||||||
- else
|
- else
|
||||||
|
@ -57,5 +50,5 @@
|
||||||
If you will be added to project - it will be displayed here
|
If you will be added to project - it will be displayed here
|
||||||
|
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){ Pager.init(20); });
|
$(function(){ Pager.init(20); });
|
||||||
|
|
|
@ -23,5 +23,3 @@
|
||||||
= preserve do
|
= preserve do
|
||||||
sudo chmod -R 770 /home/git/repositories/
|
sudo chmod -R 770 /home/git/repositories/
|
||||||
sudo chown -R git:git /home/git/repositories/
|
sudo chown -R git:git /home/git/repositories/
|
||||||
sudo chown gitlab:gitlab /home/git/repositories/**/hooks/post-receive
|
|
||||||
|
|
||||||
|
|
|
@ -31,3 +31,6 @@
|
||||||
|
|
||||||
%li
|
%li
|
||||||
%h5= link_to "Gitlab Markdown", help_markdown_path
|
%h5= link_to "Gitlab Markdown", help_markdown_path
|
||||||
|
|
||||||
|
%li
|
||||||
|
%h5= link_to "SSH keys", help_ssh_path
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
%h3 Permissions
|
%h3.page_title Permissions
|
||||||
.back_link
|
.back_link
|
||||||
= link_to help_path do
|
= link_to help_path do
|
||||||
← to index
|
← to index
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
|
|
25
app/views/help/ssh.html.haml
Normal file
25
app/views/help/ssh.html.haml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
%h3.page_title SSH Keys
|
||||||
|
.back_link
|
||||||
|
= link_to help_path do
|
||||||
|
← to index
|
||||||
|
%hr
|
||||||
|
|
||||||
|
%p.slead
|
||||||
|
SSH key allows you to establish a secure connection between your computer and Gitlab
|
||||||
|
|
||||||
|
%p.slead
|
||||||
|
To generate a new SSH key just open your terminal and use code below.
|
||||||
|
|
||||||
|
%pre.dark
|
||||||
|
ssh-keygen -t rsa -C "#{current_user.email}"
|
||||||
|
|
||||||
|
\# Creates a new ssh key using the provided email
|
||||||
|
\# Generating public/private rsa key pair...
|
||||||
|
|
||||||
|
%p.slead
|
||||||
|
Next just use code below to dump your public key and add to GITLAB SSH Keys
|
||||||
|
|
||||||
|
%pre.dark
|
||||||
|
cat ~/.ssh/id_rsa.pub
|
||||||
|
|
||||||
|
\# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....
|
|
@ -1,10 +1,10 @@
|
||||||
%h3 System hooks
|
%h3 System hooks
|
||||||
.back_link
|
.back_link
|
||||||
= link_to :back do
|
= link_to :back do
|
||||||
← back
|
← back
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
%p.slead
|
%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 request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
|
||||||
%br
|
%br
|
||||||
System Hooks can be used for logging or change information in LDAP server.
|
System Hooks can be used for logging or change information in LDAP server.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
%h3 Web hooks
|
%h3.page_title Web hooks
|
||||||
.back_link
|
.back_link
|
||||||
= link_to help_path do
|
= link_to help_path do
|
||||||
← to index
|
← to index
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
%p.slead
|
%p.slead
|
||||||
Every Gitlab project can trigger a web server whenever the repo is pushed to.
|
Every Gitlab project can trigger a web server whenever the repo is pushed to.
|
||||||
%br
|
%br
|
||||||
Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
|
Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
|
||||||
%br
|
%br
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
- bash_lexer = Pygments::Lexer[:bash]
|
%h3.page_title Workflow
|
||||||
%h3 Workflow
|
|
||||||
.back_link
|
.back_link
|
||||||
= link_to help_path do
|
= link_to help_path do
|
||||||
← to index
|
← to index
|
||||||
%hr
|
%hr
|
||||||
|
|
||||||
|
@ -9,25 +8,25 @@
|
||||||
%li
|
%li
|
||||||
%p Clone project
|
%p Clone project
|
||||||
.bash
|
.bash
|
||||||
%pre
|
%pre.dark
|
||||||
git clone git@example.com:project-name.git
|
git clone git@example.com:project-name.git
|
||||||
|
|
||||||
%li
|
%li
|
||||||
%p Create branch with your feature
|
%p Create branch with your feature
|
||||||
.bash
|
.bash
|
||||||
%pre
|
%pre.dark
|
||||||
git checkout -b $feature_name
|
git checkout -b $feature_name
|
||||||
|
|
||||||
%li
|
%li
|
||||||
%p Write code. Commit changes
|
%p Write code. Commit changes
|
||||||
.bash
|
.bash
|
||||||
%pre
|
%pre.dark
|
||||||
git commit -am "My feature is ready"
|
git commit -am "My feature is ready"
|
||||||
|
|
||||||
%li
|
%li
|
||||||
%p Push your branch to gitlabhq
|
%p Push your branch to gitlabhq
|
||||||
.bash
|
.bash
|
||||||
%pre
|
%pre.dark
|
||||||
git push origin $feature_name
|
git push origin $feature_name
|
||||||
|
|
||||||
%li
|
%li
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
Read more about web hooks
|
Read more about web hooks
|
||||||
%strong #{link_to "here", help_web_hooks_path, class: "vlink"}
|
%strong #{link_to "here", help_web_hooks_path, class: "vlink"}
|
||||||
|
|
||||||
= form_for [@project, @hook], as: :hook, url: project_hooks_path(@project) do |f|
|
= form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-inline' } do |f|
|
||||||
-if @hook.errors.any?
|
-if @hook.errors.any?
|
||||||
.alert-message.block-message.error
|
.alert-message.block-message.error
|
||||||
- @hook.errors.full_messages.each do |msg|
|
- @hook.errors.full_messages.each do |msg|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
%div.issue-form-holder
|
%div.issue-form-holder
|
||||||
%h3= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
|
%h3.page_title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
|
||||||
= form_for [@project, @issue], remote: request.xhr? do |f|
|
= form_for [@project, @issue], remote: request.xhr? do |f|
|
||||||
-if @issue.errors.any?
|
-if @issue.errors.any?
|
||||||
.alert-message.block-message.error
|
.alert-message.block-message.error
|
||||||
|
@ -9,26 +9,26 @@
|
||||||
.issue_form_box
|
.issue_form_box
|
||||||
.issue_title
|
.issue_title
|
||||||
.clearfix
|
.clearfix
|
||||||
= f.label :title do
|
= f.label :title do
|
||||||
%strong= "Subject *"
|
%strong= "Subject *"
|
||||||
.input
|
.input
|
||||||
= f.text_field :title, maxlength: 255, class: "xxlarge"
|
= f.text_field :title, maxlength: 255, class: "xxlarge"
|
||||||
.issue_middle_block
|
.issue_middle_block
|
||||||
.issue_assignee
|
.issue_assignee
|
||||||
= f.label :assignee_id do
|
= f.label :assignee_id do
|
||||||
%i.icon-user
|
%i.icon-user
|
||||||
Assign to
|
Assign to
|
||||||
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
|
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
|
||||||
.issue_milestone
|
.issue_milestone
|
||||||
= f.label :milestone_id do
|
= f.label :milestone_id do
|
||||||
%i.icon-time
|
%i.icon-time
|
||||||
Milestone
|
Milestone
|
||||||
.input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
|
.input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
|
||||||
|
|
||||||
.issue_description
|
.issue_description
|
||||||
.clearfix
|
.clearfix
|
||||||
= f.label :label_list do
|
= f.label :label_list do
|
||||||
%i.icon-tag
|
%i.icon-tag
|
||||||
Labels
|
Labels
|
||||||
.input
|
.input
|
||||||
= f.text_field :label_list, maxlength: 2000, class: "xxlarge"
|
= f.text_field :label_list, maxlength: 2000, class: "xxlarge"
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
%li{class: "#{'active' if current_page?(project_milestones_path(@project))}"}
|
%li{class: "#{'active' if current_page?(project_milestones_path(@project))}"}
|
||||||
= link_to project_milestones_path(@project), class: "tab" do
|
= link_to project_milestones_path(@project), class: "tab" do
|
||||||
Milestones
|
Milestones
|
||||||
|
%li{class: "#{'active' if current_page?(project_labels_path(@project))}"}
|
||||||
|
= link_to project_labels_path(@project), class: "tab" do
|
||||||
|
Labels
|
||||||
%li.right
|
%li.right
|
||||||
%span.rss-icon
|
%span.rss-icon
|
||||||
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
|
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
.span5
|
.span5
|
||||||
- if can? current_user, :write_issue, @project
|
- if can? current_user, :write_issue, @project
|
||||||
= link_to new_project_issue_path(@project), class: "right btn small", title: "New Issue", remote: true do
|
= link_to new_project_issue_path(@project), class: "right btn small", title: "New Issue", remote: true do
|
||||||
|
%i.icon-plus
|
||||||
New Issue
|
New Issue
|
||||||
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do
|
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do
|
||||||
= hidden_field_tag :project_id, @project.id, { id: 'project_id' }
|
= hidden_field_tag :project_id, @project.id, { id: 'project_id' }
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
.issues_bulk_update.hide
|
.issues_bulk_update.hide
|
||||||
= form_tag bulk_update_project_issues_path(@project), method: :post do
|
= form_tag bulk_update_project_issues_path(@project), method: :post do
|
||||||
%span.update_issues_text Update selected issues with
|
%span.update_issues_text Update selected issues with
|
||||||
.left
|
.left
|
||||||
= select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status")
|
= select_tag('update[status]', options_for_select(['open', 'closed']), prompt: "Status")
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
= select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + @project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), prompt: "Milestone")
|
= 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]
|
= hidden_field_tag :f, params[:f]
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
||||||
%ul#issues-table.unstyled.issues_table
|
%ul#issues-table.unstyled.issues_table
|
||||||
= render "issues"
|
= render "issues"
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,13 @@
|
||||||
.input= f.text_field :title
|
.input= f.text_field :title
|
||||||
.clearfix
|
.clearfix
|
||||||
= f.label :key
|
= f.label :key
|
||||||
.input= f.text_area :key, class: [:xxlarge, :thin_area]
|
.input
|
||||||
|
= f.text_area :key, class: [:xxlarge, :thin_area]
|
||||||
|
%p.hint
|
||||||
|
Paste your public key here. Read more about how generate it
|
||||||
|
= link_to "here", help_ssh_path
|
||||||
|
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.submit 'Save', class: "primary btn"
|
= f.submit 'Save', class: "primary btn"
|
||||||
= link_to "Cancel", keys_path, class: "btn"
|
= link_to "Cancel", keys_path, class: "btn"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
%h3.page_title New key
|
%h3.page_title Add an SSH Key
|
||||||
%hr
|
%hr
|
||||||
= render 'form'
|
= render 'form'
|
||||||
|
|
||||||
|
|
4
app/views/labels/_label.html.haml
Normal file
4
app/views/labels/_label.html.haml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
%li.wll
|
||||||
|
%strong= label.name
|
||||||
|
.right
|
||||||
|
%span= pluralize label.count, 'issue'
|
14
app/views/labels/index.html.haml
Normal file
14
app/views/labels/index.html.haml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
= render "issues/head"
|
||||||
|
|
||||||
|
%h3.page_title
|
||||||
|
Labels
|
||||||
|
%br
|
||||||
|
%div.ui-box
|
||||||
|
%ul.unstyled.labels-table
|
||||||
|
- @labels.each do |label|
|
||||||
|
= render 'label', label: label
|
||||||
|
|
||||||
|
- unless @labels.present?
|
||||||
|
%li
|
||||||
|
%h3.nothing_here_message Nothing to show here
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
= favicon_link_tag 'favicon.ico'
|
= favicon_link_tag 'favicon.ico'
|
||||||
= stylesheet_link_tag "application"
|
= stylesheet_link_tag "application"
|
||||||
= javascript_include_tag "application"
|
= javascript_include_tag "application"
|
||||||
|
|
||||||
-# Atom feed
|
-# Atom feed
|
||||||
- if controller_name == 'projects' && action_name == 'index'
|
- if controller_name == 'projects' && action_name == 'index'
|
||||||
= auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed"
|
= auto_discovery_link_tag :atom, projects_url(:atom, private_token: current_user.private_token), title: "Dashboard feed"
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".edit_merge_request").live("ajax:beforeSend", function() {
|
$(".edit_merge_request").live("ajax:beforeSend", function() {
|
||||||
$(this).replaceWith('#{image_tag "ajax_loader.gif"}');
|
$('.can_be_merged').hide();
|
||||||
|
$('.merge_in_progress').show();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
%a.close{href: "#"} ×
|
%a.close{href: "#"} ×
|
||||||
%h3 How To Merge
|
%h3 How To Merge
|
||||||
.modal-body
|
.modal-body
|
||||||
%pre
|
%pre.dark
|
||||||
= preserve do
|
= preserve do
|
||||||
:erb
|
git checkout #{@merge_request.target_branch}
|
||||||
git checkout <%= @merge_request.target_branch %>
|
git fetch origin
|
||||||
git fetch origin
|
git merge origin/#{@merge_request.source_branch}
|
||||||
git merge origin/<%= @merge_request.source_branch %>
|
git push origin #{@merge_request.target_branch}
|
||||||
git push origin <%= @merge_request.target_branch %>
|
|
||||||
|
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
|
|
|
@ -40,3 +40,6 @@
|
||||||
.alert.alert-info
|
.alert.alert-info
|
||||||
%strong This merge request already can not be merged. Try to reload page.
|
%strong This merge request already can not be merged. Try to reload page.
|
||||||
|
|
||||||
|
.merge_in_progress.hide
|
||||||
|
%span.cgray Merge is in progress. Please wait. Page will be automatically reloaded.
|
||||||
|
= image_tag "ajax_loader.gif"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
%h3= @milestone.new_record? ? "New Milestone" : "Edit Milestone ##{@milestone.id}"
|
%h3.page_title= @milestone.new_record? ? "New Milestone" : "Edit Milestone ##{@milestone.id}"
|
||||||
.back_link
|
.back_link
|
||||||
= link_to project_milestones_path(@project) do
|
= link_to project_milestones_path(@project) do
|
||||||
← To milestones
|
← To milestones
|
||||||
|
@ -17,12 +17,12 @@
|
||||||
= f.label :title, "Title", class: "control-label"
|
= f.label :title, "Title", class: "control-label"
|
||||||
.controls
|
.controls
|
||||||
= f.text_field :title, maxlength: 255, class: "input-xlarge"
|
= f.text_field :title, maxlength: 255, class: "input-xlarge"
|
||||||
%p.help-block Required
|
%p.hint Required
|
||||||
.control-group
|
.control-group
|
||||||
= f.label :description, "Description", class: "control-label"
|
= f.label :description, "Description", class: "control-label"
|
||||||
.controls
|
.controls
|
||||||
= f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10
|
= f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10
|
||||||
%p.help-block Markdown is enabled.
|
%p.hint Markdown is enabled.
|
||||||
.span6
|
.span6
|
||||||
.control-group
|
.control-group
|
||||||
= f.label :due_date, "Due Date", class: "control-label"
|
= f.label :due_date, "Due Date", class: "control-label"
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
- if note.valid?
|
- if note.valid?
|
||||||
:plain
|
:plain
|
||||||
$("#new_note .errors").remove();
|
$("#new_note .error").remove();
|
||||||
$('#new_note textarea').val("");
|
$('#new_note textarea').val("");
|
||||||
|
$('#preview-link').text('Preview');
|
||||||
|
$('#preview-note').hide(); $('#note_note').show();
|
||||||
NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
|
NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
|
||||||
- else
|
- else
|
||||||
:plain
|
:plain
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
%li{id: dom_id(note), class: "note"}
|
%li{id: dom_id(note), class: "note"}
|
||||||
= image_tag gravatar_icon(note.author.email), class: "avatar"
|
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
||||||
%div.note-author
|
%div.note-author
|
||||||
%strong= note.author_name
|
%strong= note.author_name
|
||||||
= link_to "##{dom_id(note)}", name: dom_id(note) do
|
= link_to "##{dom_id(note)}", name: dom_id(note) do
|
||||||
|
|
|
@ -1,47 +1,30 @@
|
||||||
- if current_user.require_ssh_key?
|
= render 'shared/no_ssh'
|
||||||
.alert-message.block-message.error
|
|
||||||
%ul
|
|
||||||
%li You have no ssh keys added to your profile.
|
|
||||||
%li You wont be able to pull/push repository.
|
|
||||||
%li Visit profile → keys and add public key of every machine you want to use for work with gitlabhq.
|
|
||||||
|
|
||||||
.alert-message.block-message.error
|
|
||||||
%ul.unstyled.alert_holder
|
|
||||||
%li You should push repository to proceed.
|
|
||||||
%li After push you will be able to browse code, commits etc.
|
|
||||||
|
|
||||||
- bash_lexer = Pygments::Lexer[:bash]
|
|
||||||
%div.git-empty
|
%div.git-empty
|
||||||
%h3 Git global setup:
|
%h4 Git global setup:
|
||||||
- setup_str = ["git config --global user.name \"#{current_user.name}\"",
|
%pre.dark
|
||||||
"git config --global user.email \"#{current_user.email}\""].join("\n")
|
= preserve do
|
||||||
= preserve do
|
git config --global user.name "#{current_user.name}"
|
||||||
= raw bash_lexer.highlight(setup_str, lexer: 'bash', options: {encoding: 'utf-8'})
|
git config --global user.email "#{current_user.email}"
|
||||||
|
|
||||||
%br
|
%h4.prepend-top-20 Create Repository
|
||||||
%br
|
%pre.dark
|
||||||
%h3 Create Repository
|
= preserve do
|
||||||
- repo_setup_str = ["mkdir #{@project.path}",
|
mkdir #{@project.path}
|
||||||
"cd #{@project.path}",
|
cd #{@project.path}
|
||||||
"git init",
|
git init
|
||||||
"touch README",
|
touch README
|
||||||
"git add README",
|
git add README
|
||||||
"git commit -m 'first commit'",
|
git commit -m 'first commit'
|
||||||
"git remote add origin #{@project.url_to_repo}",
|
git remote add origin #{@project.url_to_repo}
|
||||||
"git push -u origin master"].join("\n")
|
git push -u origin master
|
||||||
|
|
||||||
= preserve do
|
%h4.prepend-top-20 Existing Git Repo?
|
||||||
= raw bash_lexer.highlight(repo_setup_str)
|
%pre.dark
|
||||||
|
= preserve do
|
||||||
%br
|
cd existing_git_repo
|
||||||
%br
|
git remote add origin #{@project.url_to_repo}
|
||||||
%h3 Existing Git Repo?
|
git push -u origin master
|
||||||
- exist_repo_setup_str = ["cd existing_git_repo",
|
|
||||||
"git remote add origin #{@project.url_to_repo}",
|
|
||||||
"git push -u origin master"].join("\n")
|
|
||||||
= preserve do
|
|
||||||
= raw bash_lexer.highlight(exist_repo_setup_str)
|
|
||||||
|
|
||||||
- if can? current_user, :admin_project, @project
|
- if can? current_user, :admin_project, @project
|
||||||
.alert-message.block-message.error.prepend-top-20
|
.prepend-top-20
|
||||||
= link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger"
|
= link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right"
|
||||||
|
|
|
@ -51,8 +51,6 @@
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){
|
$(function(){
|
||||||
$('select#branch').selectmenu({style:'popup', width:200});
|
|
||||||
$('select#tag').selectmenu({style:'popup', width:200});
|
|
||||||
$('.project-refs-select').chosen();
|
$('.project-refs-select').chosen();
|
||||||
|
|
||||||
history.pushState({ path: this.path }, '', "#{@history_path}");
|
history.pushState({ path: this.path }, '', "#{@history_path}");
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
- if tm
|
- if tm
|
||||||
%strong= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm)
|
= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm)
|
||||||
= link_to_gfm truncate(content_commit.title, length: tm ? 30 : 50), project_commit_path(@project, content_commit.id), class: "tree-commit-link"
|
= link_to_gfm truncate(content_commit.title, length: tm ? 30 : 50), project_commit_path(@project, content_commit.id), class: "tree-commit-link"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
= form_tag search_path, method: :get do |f|
|
= form_tag search_path, method: :get, class: 'form-inline' do |f|
|
||||||
.padded
|
.padded
|
||||||
= label_tag :search do
|
= label_tag :search do
|
||||||
%strong Looking for
|
%strong Looking for
|
||||||
|
|
8
app/views/shared/_no_ssh.html.haml
Normal file
8
app/views/shared/_no_ssh.html.haml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
- if current_user.require_ssh_key?
|
||||||
|
%h6.error_message
|
||||||
|
%span
|
||||||
|
You wont be able to pull/push project code unless you
|
||||||
|
%strong
|
||||||
|
= link_to new_key_path, class: "vlink" do
|
||||||
|
add SSH key
|
||||||
|
to your profile
|
|
@ -9,7 +9,7 @@
|
||||||
%span.label Blocked
|
%span.label Blocked
|
||||||
|
|
||||||
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
|
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
|
||||||
= image_tag gravatar_icon(user.email, 40), class: "avatar"
|
= image_tag gravatar_icon(user.email, 40), class: "avatar s32"
|
||||||
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
|
= link_to project_team_member_path(@project, member), title: user.name, class: "dark" do
|
||||||
%strong= truncate(user.name, lenght: 40)
|
%strong= truncate(user.name, lenght: 40)
|
||||||
%br
|
%br
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
= form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
|
= form_for(@team_member, as: :team_member, url: project_team_member_path(@project, @team_member)) do |f|
|
||||||
= f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
|
= f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, class: "project-access-select", disabled: !allow_admin
|
||||||
%hr
|
%hr
|
||||||
= render user.recent_events.limit(5)
|
= render @events
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){
|
$(function(){
|
||||||
$('.repo-access-select, .project-access-select').live("change", function() {
|
$('.repo-access-select, .project-access-select').live("change", function() {
|
||||||
|
|
|
@ -44,5 +44,8 @@ module Gitlab
|
||||||
|
|
||||||
# Version of your assets, change this if you want to expire all your assets
|
# Version of your assets, change this if you want to expire all your assets
|
||||||
config.assets.version = '1.0'
|
config.assets.version = '1.0'
|
||||||
|
|
||||||
|
# Add fonts
|
||||||
|
config.assets.paths << "#{Rails.root}/app/assets/fonts"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,7 @@ app:
|
||||||
default_projects_limit: 10
|
default_projects_limit: 10
|
||||||
# backup_path: "/vol/backups" # default: Rails.root + backups/
|
# backup_path: "/vol/backups" # default: Rails.root + backups/
|
||||||
# backup_keep_time: 604800 # default: 0 (forever) (in seconds)
|
# backup_keep_time: 604800 # default: 0 (forever) (in seconds)
|
||||||
|
# disable_gravatar: true # default: false - Disable user avatars from Gravatar.com
|
||||||
|
|
||||||
#
|
#
|
||||||
# 2. Advanced settings:
|
# 2. Advanced settings:
|
||||||
|
@ -39,7 +39,6 @@ git_host:
|
||||||
receive_pack: true
|
receive_pack: true
|
||||||
# port: 22
|
# port: 22
|
||||||
|
|
||||||
|
|
||||||
# Git settings
|
# Git settings
|
||||||
# Use default values unless you understand it
|
# Use default values unless you understand it
|
||||||
git:
|
git:
|
||||||
|
|
|
@ -120,5 +120,8 @@ class Settings < Settingslogic
|
||||||
omniauth['providers'] || []
|
omniauth['providers'] || []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_gravatar?
|
||||||
|
app['disable_gravatar'] || false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#if defined?(Footnotes) && Rails.env.development?
|
|
||||||
#Footnotes.run! # first of all
|
|
||||||
#end
|
|
|
@ -30,6 +30,7 @@ Gitlab::Application.routes.draw do
|
||||||
get 'help/web_hooks' => 'help#web_hooks'
|
get 'help/web_hooks' => 'help#web_hooks'
|
||||||
get 'help/system_hooks' => 'help#system_hooks'
|
get 'help/system_hooks' => 'help#system_hooks'
|
||||||
get 'help/markdown' => 'help#markdown'
|
get 'help/markdown' => 'help#markdown'
|
||||||
|
get 'help/ssh' => 'help#ssh'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Admin Area
|
# Admin Area
|
||||||
|
@ -196,7 +197,9 @@ Gitlab::Application.routes.draw do
|
||||||
end
|
end
|
||||||
resources :team_members
|
resources :team_members
|
||||||
resources :milestones
|
resources :milestones
|
||||||
|
resources :labels, :only => [:index]
|
||||||
resources :issues do
|
resources :issues do
|
||||||
|
|
||||||
collection do
|
collection do
|
||||||
post :sort
|
post :sort
|
||||||
post :bulk_update
|
post :bulk_update
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
class AddExternAuthProviderToUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :users, :extern_uid, :string
|
||||||
|
add_column :users, :provider, :string
|
||||||
|
|
||||||
|
add_index :users, [:extern_uid, :provider], :unique => true
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +0,0 @@
|
||||||
class AddProviderAndUidToUsers < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
add_column :users, :provider, :string
|
|
||||||
add_column :users, :uid, :string
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -171,11 +171,12 @@ ActiveRecord::Schema.define(:version => 20120803152018) do
|
||||||
t.boolean "blocked", :default => false, :null => false
|
t.boolean "blocked", :default => false, :null => false
|
||||||
t.integer "failed_attempts", :default => 0
|
t.integer "failed_attempts", :default => 0
|
||||||
t.datetime "locked_at"
|
t.datetime "locked_at"
|
||||||
|
t.string "extern_uid"
|
||||||
t.string "provider"
|
t.string "provider"
|
||||||
t.string "uid"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
|
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
|
||||||
|
add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true
|
||||||
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
|
add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
|
||||||
|
|
||||||
create_table "users_projects", :force => true do |t|
|
create_table "users_projects", :force => true do |t|
|
||||||
|
|
|
@ -119,7 +119,6 @@ Permissions:
|
||||||
|
|
||||||
sudo chmod -R g+rwX /home/git/repositories/
|
sudo chmod -R g+rwX /home/git/repositories/
|
||||||
sudo chown -R git:git /home/git/repositories/
|
sudo chown -R git:git /home/git/repositories/
|
||||||
sudo chown gitlab:gitlab /home/git/repositories/**/hooks/post-receive
|
|
||||||
|
|
||||||
#### CHECK: Logout & login again to apply git group to your user
|
#### CHECK: Logout & login again to apply git group to your user
|
||||||
|
|
||||||
|
@ -134,7 +133,7 @@ Permissions:
|
||||||
|
|
||||||
# 4. Install gitlab and configuration. Check status configuration.
|
# 4. Install gitlab and configuration. Check status configuration.
|
||||||
|
|
||||||
sudo gem install charlock_holmes
|
sudo gem install charlock_holmes --version '0.6.8'
|
||||||
sudo pip install pygments
|
sudo pip install pygments
|
||||||
sudo gem install bundler
|
sudo gem install bundler
|
||||||
cd /home/gitlab
|
cd /home/gitlab
|
||||||
|
@ -177,6 +176,11 @@ Permissions:
|
||||||
#### Setup DB
|
#### Setup DB
|
||||||
|
|
||||||
sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
|
sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
|
||||||
|
|
||||||
|
#### Setup gitlab hooks
|
||||||
|
|
||||||
|
sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
|
||||||
|
sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
|
||||||
|
|
||||||
Checking status:
|
Checking status:
|
||||||
|
|
||||||
|
@ -196,6 +200,7 @@ Checking status:
|
||||||
Resolving deltas: 100% (174/174), done.
|
Resolving deltas: 100% (174/174), done.
|
||||||
Can clone gitolite-admin?............YES
|
Can clone gitolite-admin?............YES
|
||||||
UMASK for .gitolite.rc is 0007? ............YES
|
UMASK for .gitolite.rc is 0007? ............YES
|
||||||
|
/home/git/share/gitolite/hooks/common/post-receive exists? ............YES
|
||||||
|
|
||||||
If you got all YES - congrats! You can go to next step.
|
If you got all YES - congrats! You can go to next step.
|
||||||
|
|
||||||
|
|
13
features/projects/issues/labels.feature
Normal file
13
features/projects/issues/labels.feature
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
Feature: Labels
|
||||||
|
Background:
|
||||||
|
Given I signin as a user
|
||||||
|
And I own project "Shop"
|
||||||
|
And project "Shop" have issues tags:
|
||||||
|
| name |
|
||||||
|
| bug |
|
||||||
|
| feature |
|
||||||
|
Given I visit project "Shop" labels page
|
||||||
|
|
||||||
|
Scenario: I should see active milestones
|
||||||
|
Then I should see label "bug"
|
||||||
|
And I should see label "feature"
|
|
@ -4,9 +4,7 @@ Feature: Project Network Graph
|
||||||
Background:
|
Background:
|
||||||
Given I signin as a user
|
Given I signin as a user
|
||||||
And I own project "Shop"
|
And I own project "Shop"
|
||||||
And I visit project "Shop" network page
|
And I visit project "Shop" network page
|
||||||
|
|
||||||
Scenario: I should see project network
|
Scenario: I should see project network
|
||||||
Then page should have network graph
|
Then page should have network graph
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -91,36 +91,28 @@ Then /^I should see my merge requests$/ do
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^I have assigned issues$/ do
|
Given /^I have assigned issues$/ do
|
||||||
project1 = Factory :project,
|
project = Factory :project
|
||||||
:path => "project1",
|
project.add_access(@user, :read, :write)
|
||||||
:code => "TEST1"
|
|
||||||
|
|
||||||
project2 = Factory :project,
|
|
||||||
:path => "project2",
|
|
||||||
:code => "TEST2"
|
|
||||||
|
|
||||||
project1.add_access(@user, :read, :write)
|
|
||||||
project2.add_access(@user, :read, :write)
|
|
||||||
|
|
||||||
issue1 = Factory :issue,
|
issue1 = Factory :issue,
|
||||||
:author => @user,
|
:author => @user,
|
||||||
:assignee => @user,
|
:assignee => @user,
|
||||||
:project => project1
|
:project => project
|
||||||
|
|
||||||
issue2 = Factory :issue,
|
issue2 = Factory :issue,
|
||||||
:author => @user,
|
:author => @user,
|
||||||
:assignee => @user,
|
:assignee => @user,
|
||||||
:project => project2
|
:project => project
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^I have authored merge requests$/ do
|
Given /^I have authored merge requests$/ do
|
||||||
project1 = Factory :project,
|
project1 = Factory :project,
|
||||||
:path => "project1",
|
:path => "gitlabhq_1",
|
||||||
:code => "TEST1"
|
:code => "gitlabhq_1"
|
||||||
|
|
||||||
project2 = Factory :project,
|
project2 = Factory :project,
|
||||||
:path => "project2",
|
:path => "gitlabhq_2",
|
||||||
:code => "TEST2"
|
:code => "gitlabhq_2"
|
||||||
|
|
||||||
project1.add_access(@user, :read, :write)
|
project1.add_access(@user, :read, :write)
|
||||||
project2.add_access(@user, :read, :write)
|
project2.add_access(@user, :read, :write)
|
||||||
|
|
|
@ -33,6 +33,25 @@ Given /^I visit issue page "(.*?)"$/ do |arg1|
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^I submit new issue "(.*?)"$/ do |arg1|
|
Given /^I submit new issue "(.*?)"$/ do |arg1|
|
||||||
fill_in "issue_title", :with => arg1
|
fill_in "issue_title", with: arg1
|
||||||
click_button "Submit new issue"
|
click_button "Submit new issue"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Given /^project "(.*?)" have issues tags:$/ do |arg1, table|
|
||||||
|
project = Project.find_by_name(arg1)
|
||||||
|
table.hashes.each do |hash|
|
||||||
|
Factory :issue,
|
||||||
|
project: project,
|
||||||
|
label_list: [hash[:name]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Given /^I visit project "(.*?)" labels page$/ do |arg1|
|
||||||
|
visit project_labels_path(Project.find_by_name(arg1))
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^I should see label "(.*?)"$/ do |arg1|
|
||||||
|
within ".labels-table" do
|
||||||
|
page.should have_content arg1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -57,6 +57,11 @@ end
|
||||||
|
|
||||||
Given /^I visit project "(.*?)" network page$/ do |arg1|
|
Given /^I visit project "(.*?)" network page$/ do |arg1|
|
||||||
project = Project.find_by_name(arg1)
|
project = Project.find_by_name(arg1)
|
||||||
|
|
||||||
|
# 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)
|
visit graph_project_path(project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,8 +72,8 @@ end
|
||||||
Given /^page should have network graph$/ do
|
Given /^page should have network graph$/ do
|
||||||
page.should have_content "Project Network Graph"
|
page.should have_content "Project Network Graph"
|
||||||
within ".graph" do
|
within ".graph" do
|
||||||
page.should have_content "stable"
|
page.should have_content "master"
|
||||||
page.should have_content "notes_refacto..."
|
page.should have_content "scss_refactor..."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
require 'simplecov'
|
unless ENV['CI']
|
||||||
SimpleCov.start 'rails'
|
require 'simplecov'
|
||||||
|
SimpleCov.start 'rails'
|
||||||
|
end
|
||||||
|
|
||||||
require 'cucumber/rails'
|
require 'cucumber/rails'
|
||||||
require 'webmock/cucumber'
|
require 'webmock/cucumber'
|
||||||
|
@ -39,3 +41,10 @@ rescue NameError
|
||||||
end
|
end
|
||||||
|
|
||||||
Cucumber::Rails::Database.javascript_strategy = :truncation
|
Cucumber::Rails::Database.javascript_strategy = :truncation
|
||||||
|
|
||||||
|
require 'headless'
|
||||||
|
|
||||||
|
headless = Headless.new
|
||||||
|
headless.start
|
||||||
|
|
||||||
|
require 'cucumber/rspec/doubles'
|
||||||
|
|
31
lib/color.rb
31
lib/color.rb
|
@ -1,31 +0,0 @@
|
||||||
module Color
|
|
||||||
extend self
|
|
||||||
|
|
||||||
def colorize(text, color_code)
|
|
||||||
"\033[#{color_code}#{text}\033[0m"
|
|
||||||
end
|
|
||||||
|
|
||||||
def red(text)
|
|
||||||
colorize(text, "31m")
|
|
||||||
end
|
|
||||||
|
|
||||||
def green(text)
|
|
||||||
colorize(text, "32m")
|
|
||||||
end
|
|
||||||
|
|
||||||
def yellow(text)
|
|
||||||
colorize(text, "93m")
|
|
||||||
end
|
|
||||||
|
|
||||||
def command(string)
|
|
||||||
`#{string}`
|
|
||||||
if $?.to_i > 0
|
|
||||||
puts red " == #{string} - FAIL"
|
|
||||||
puts red " == Error during configure"
|
|
||||||
exit
|
|
||||||
else
|
|
||||||
puts green " == #{string} - OK"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
183
lib/gitlab/graph_commit.rb
Normal file
183
lib/gitlab/graph_commit.rb
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
require "grit"
|
||||||
|
|
||||||
|
module Gitlab
|
||||||
|
class GraphCommit
|
||||||
|
attr_accessor :time, :space
|
||||||
|
attr_accessor :refs
|
||||||
|
|
||||||
|
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<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}
|
||||||
|
# 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<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}
|
||||||
|
# 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<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
|
||||||
|
|
||||||
|
|
||||||
|
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] = 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
|
|
@ -1,5 +1,14 @@
|
||||||
module Gitlab
|
module Gitlab
|
||||||
# Custom parsing for Gitlab-flavored 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
|
||||||
#
|
#
|
||||||
# Examples
|
# Examples
|
||||||
#
|
#
|
||||||
|
@ -67,25 +76,25 @@ module Gitlab
|
||||||
def reference_user(identifier)
|
def reference_user(identifier)
|
||||||
if user = @project.users.where(name: identifier).first
|
if user = @project.users.where(name: identifier).first
|
||||||
member = @project.users_projects.where(user_id: user).first
|
member = @project.users_projects.where(user_id: user).first
|
||||||
link_to("@#{user.name}", project_team_member_path(@project, member), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) if member
|
link_to("@#{identifier}", project_team_member_path(@project, member), html_options.merge(class: "gfm gfm-team_member #{html_options[:class]}")) if member
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reference_issue(identifier)
|
def reference_issue(identifier)
|
||||||
if issue = @project.issues.where(id: identifier).first
|
if issue = @project.issues.where(id: identifier).first
|
||||||
link_to("##{issue.id}", project_issue_path(@project, issue), html_options.merge(title: "Issue: #{issue.title}", class: "gfm gfm-issue #{html_options[:class]}"))
|
link_to("##{identifier}", project_issue_path(@project, issue), html_options.merge(title: "Issue: #{issue.title}", class: "gfm gfm-issue #{html_options[:class]}"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reference_merge_request(identifier)
|
def reference_merge_request(identifier)
|
||||||
if merge_request = @project.merge_requests.where(id: identifier).first
|
if merge_request = @project.merge_requests.where(id: identifier).first
|
||||||
link_to("!#{merge_request.id}", project_merge_request_path(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}"))
|
link_to("!#{identifier}", project_merge_request_path(@project, merge_request), html_options.merge(title: "Merge Request: #{merge_request.title}", class: "gfm gfm-merge_request #{html_options[:class]}"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reference_snippet(identifier)
|
def reference_snippet(identifier)
|
||||||
if snippet = @project.snippets.where(id: identifier).first
|
if snippet = @project.snippets.where(id: identifier).first
|
||||||
link_to("$#{snippet.id}", project_snippet_path(@project, snippet), html_options.merge(title: "Snippet: #{snippet.title}", class: "gfm gfm-snippet #{html_options[:class]}"))
|
link_to("$#{identifier}", project_snippet_path(@project, snippet), html_options.merge(title: "Snippet: #{snippet.title}", class: "gfm gfm-snippet #{html_options[:class]}"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,181 +0,0 @@
|
||||||
require "grit"
|
|
||||||
|
|
||||||
class GraphCommit
|
|
||||||
attr_accessor :time, :space
|
|
||||||
attr_accessor :refs
|
|
||||||
|
|
||||||
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<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}
|
|
||||||
# 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<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}
|
|
||||||
# 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<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
|
|
||||||
|
|
||||||
|
|
||||||
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] = 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
|
|
|
@ -1,26 +0,0 @@
|
||||||
namespace :dev do
|
|
||||||
desc "Prepare for development (run dev_user.sh first)"
|
|
||||||
task :repos => :environment do
|
|
||||||
key = `sudo -u gitlabdev -H cat /home/gitlabdev/.ssh/id_rsa.pub`
|
|
||||||
raise "\n *** Run ./lib/tasks/dev/user.sh first *** \n" if key.empty?
|
|
||||||
Key.create(:user_id => User.first, :key => key, :title => "gitlabdev")
|
|
||||||
|
|
||||||
puts "\n *** Clone diaspora from github"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev; git clone git://github.com/diaspora/diaspora.git /home/gitlabdev/diaspora"`
|
|
||||||
|
|
||||||
puts "\n *** Push diaspora source to gitlab"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev/diaspora; git remote add local git@localhost:diaspora.git; git push local master; git push local --tags; git checkout -b api origin/api; git push local api; git checkout -b heroku origin/heroku; git push local heroku"`
|
|
||||||
|
|
||||||
puts "\n *** Clone rails from github"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev; git clone git://github.com/rails/rails.git /home/gitlabdev/rails"`
|
|
||||||
|
|
||||||
puts "\n *** Push rails source to gitlab"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev/rails; git remote add local git@localhost:ruby_on_rails.git; git push local master; git push local --tags"`
|
|
||||||
|
|
||||||
puts "\n *** Clone rubinius from github"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev; git clone git://github.com/rubinius/rubinius.git /home/gitlabdev/rubinius"`
|
|
||||||
|
|
||||||
puts "\n *** Push rubinius source to gitlab"
|
|
||||||
`sudo -u gitlabdev -H sh -c "cd /home/gitlabdev/rubinius; git remote add local git@localhost:rubinius.git; git push local master; git push local --tags"`
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,10 +0,0 @@
|
||||||
namespace :dev do
|
|
||||||
desc "DEV | Run cucumber and rspec"
|
|
||||||
task :tests do
|
|
||||||
["cucumber", "rspec spec"].each do |cmd|
|
|
||||||
puts "Starting to run #{cmd}..."
|
|
||||||
system("bundle exec #{cmd}")
|
|
||||||
raise "#{cmd} failed!" unless $?.exitstatus == 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +0,0 @@
|
||||||
sudo adduser \
|
|
||||||
--gecos 'gitlab dev user' \
|
|
||||||
--disabled-password \
|
|
||||||
--home /home/gitlabdev \
|
|
||||||
gitlabdev
|
|
||||||
|
|
||||||
sudo -i -u gitlabdev -H sh -c "ssh-keygen -t rsa"
|
|
|
@ -1,7 +1,11 @@
|
||||||
namespace :gitlab do
|
namespace :gitlab do
|
||||||
namespace :app do
|
namespace :app do
|
||||||
desc "GITLAB | Setup production application"
|
desc "GITLAB | Setup production application"
|
||||||
task :setup => ['db:setup', 'db:seed_fu', 'gitlab:app:enable_automerge']
|
task :setup => [
|
||||||
|
'db:setup',
|
||||||
|
'db:seed_fu',
|
||||||
|
'gitlab:app:enable_automerge'
|
||||||
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,20 @@ namespace :gitlab do
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gitolite_hooks_path = File.join("/home", Gitlab.config.ssh_user, "share", "gitolite", "hooks", "common")
|
||||||
|
gitlab_hook_files = ['post-receive']
|
||||||
|
gitlab_hook_files.each do |file_name|
|
||||||
|
dest = File.join(gitolite_hooks_path, file_name)
|
||||||
|
print "#{dest} exists? ............"
|
||||||
|
if File.exists?(dest)
|
||||||
|
puts "YES".green
|
||||||
|
else
|
||||||
|
puts "NO".red
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
if Project.count > 0
|
if Project.count > 0
|
||||||
puts "Validating projects repositories:".yellow
|
puts "Validating projects repositories:".yellow
|
||||||
Project.find_each(:batch_size => 100) do |project|
|
Project.find_each(:batch_size => 100) do |project|
|
||||||
|
@ -67,12 +81,6 @@ namespace :gitlab do
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
unless File.owned?(hook_file)
|
|
||||||
puts "post-receive file is not owner by gitlab".red
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "post-reveice file ok".green
|
puts "post-reveice file ok".green
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
namespace :gitlab do
|
|
||||||
namespace :gitolite do
|
|
||||||
desc "GITLAB | Rewrite hooks for repos"
|
|
||||||
task :update_hooks => :environment do
|
|
||||||
puts "Starting Projects"
|
|
||||||
Project.find_each(:batch_size => 100) do |project|
|
|
||||||
begin
|
|
||||||
if project.commit
|
|
||||||
project.write_hooks
|
|
||||||
print ".".green
|
|
||||||
end
|
|
||||||
rescue Exception => e
|
|
||||||
print e.message.red
|
|
||||||
end
|
|
||||||
end
|
|
||||||
puts "\nDone with projects"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
23
lib/tasks/gitlab/write_hook.rake
Normal file
23
lib/tasks/gitlab/write_hook.rake
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
namespace :gitlab do
|
||||||
|
namespace :gitolite do
|
||||||
|
desc "GITLAB | Write GITLAB hook for gitolite"
|
||||||
|
task :write_hooks => :environment do
|
||||||
|
gitolite_hooks_path = File.join("/home", Gitlab.config.ssh_user, "share", "gitolite", "hooks", "common")
|
||||||
|
gitlab_hooks_path = Rails.root.join("lib", "hooks")
|
||||||
|
|
||||||
|
gitlab_hook_files = ['post-receive']
|
||||||
|
|
||||||
|
gitlab_hook_files.each do |file_name|
|
||||||
|
source = File.join(gitlab_hooks_path, file_name)
|
||||||
|
dest = File.join(gitolite_hooks_path, file_name)
|
||||||
|
|
||||||
|
puts "sudo -u root cp #{source} #{dest}".yellow
|
||||||
|
`sudo -u root cp #{source} #{dest}`
|
||||||
|
|
||||||
|
puts "sudo -u root chown git:git #{dest}".yellow
|
||||||
|
`sudo -u root chown git:git #{dest}`
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
26
spec/helpers/application_helper_spec.rb
Normal file
26
spec/helpers/application_helper_spec.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ApplicationHelper do
|
||||||
|
describe "gravatar_icon" do
|
||||||
|
let(:user_email) { 'user@email.com' }
|
||||||
|
|
||||||
|
it "should return a generic avatar path when Gravatar is disabled" do
|
||||||
|
Gitlab.config.stub(:disable_gravatar?).and_return(true)
|
||||||
|
gravatar_icon(user_email).should == 'no_avatar.png'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return a generic avatar path when email is blank" do
|
||||||
|
gravatar_icon('').should == 'no_avatar.png'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should use SSL when appropriate" do
|
||||||
|
stub!(:request).and_return(double(:ssl? => true))
|
||||||
|
gravatar_icon(user_email).should match('https://secure.gravatar.com')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should accept a custom size" do
|
||||||
|
stub!(:request).and_return(double(:ssl? => false))
|
||||||
|
gravatar_icon(user_email, 64).should match(/\?s=64/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -24,7 +24,7 @@ describe Notify do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /Account was created for you/
|
should have_subject /^gitlab \| Account was created for you$/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'contains the new user\'s login name' do
|
it 'contains the new user\'s login name' do
|
||||||
|
@ -60,7 +60,7 @@ describe Notify do
|
||||||
it_behaves_like 'an assignee email'
|
it_behaves_like 'an assignee email'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /new issue ##{issue.id}/
|
should have_subject /new issue ##{issue.id} \| #{issue.title} \| #{project.name}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'contains a link to the new issue' do
|
it 'contains a link to the new issue' do
|
||||||
|
@ -76,7 +76,7 @@ describe Notify do
|
||||||
it_behaves_like 'a multiple recipients email'
|
it_behaves_like 'a multiple recipients email'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /changed issue/
|
should have_subject /changed issue ##{issue.id} \| #{issue.title}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'contains the name of the previous assignee' do
|
it 'contains the name of the previous assignee' do
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue