Merge branch 'master' into 90-pull

Conflicts:
	app/assets/stylesheets/design/custom.scss
	app/controllers/projects/git/commits_controller.rb
	app/helpers/git_helper.rb
	app/models/project.rb
	app/views/projects/git/commits/_commit_diff.html.haml
	db/schema.rb
	lib/ext/core/string.rb
This commit is contained in:
Alexander Machehin 2012-07-27 18:24:35 +06:00
commit 944c6fc0e2
86 changed files with 1232 additions and 766 deletions

24
Gemfile
View File

@ -2,19 +2,19 @@ source 'http://rubygems.org'
gem 'rails', '3.2.6' #, :git => 'git://github.com/rails/rails.git' gem 'rails', '3.2.6' #, :git => 'git://github.com/rails/rails.git'
gem 'pg', '~> 0.13.2' gem 'pg', '~> 0.14.0'
# gem 'silent-postgres', :git => 'git://github.com/dolzenko/silent-postgres.git' #'~> 0.1.1' # gem 'silent-postgres', :git => 'git://github.com/dolzenko/silent-postgres.git' #'~> 0.1.1'
gem 'redhillonrails_core', :git => 'git://github.com/chipiga/redhillonrails_core.git', :branch => 'rails31' # '~> 2.0.0.pre' # deprecated gem 'redhillonrails_core', :git => 'git://github.com/chipiga/redhillonrails_core.git', :branch => 'rails31' # '~> 2.0.0.pre' # deprecated
# gem 'schema_plus', '~> 0.2.1' # buggy shit! # gem 'schema_plus', '~> 0.2.1' # buggy shit!
gem 'devise', '~> 2.0.4' gem 'devise', '~> 2.1.2'
gem 'omniauth', '~> 1.0.3' gem 'omniauth', '~> 1.1.0'
gem 'omniauth-openid', '~> 1.0.1' gem 'omniauth-openid', '~> 1.0.1'
gem 'cancan', '~> 1.6.7' gem 'cancan', '1.6.7' # 1.6.8 fail specs with strange error
gem 'ancestry', '~> 1.3.0' gem 'ancestry', '~> 1.3.0'
gem 'paperclip', '~> 3.0.4' gem 'paperclip', '~> 3.1.4'
gem 'resque', '~> 1.20.0' gem 'resque', '~> 1.21.0'
gem 'resque-status', '~> 0.3.3' gem 'resque-status', '~> 0.3.3'
gem 'resque_mailer', '~> 2.1.0' gem 'resque_mailer', '~> 2.1.0'
gem 'perform_later', '~> 1.3.0' # should be after resque_mailer gem 'perform_later', '~> 1.3.0' # should be after resque_mailer
@ -26,6 +26,8 @@ gem 'state_machine'
gem 'grack', :git => 'git://github.com/rdblue/grack.git', :require => 'git_http' gem 'grack', :git => 'git://github.com/rdblue/grack.git', :require => 'git_http'
gem "grit", :git => 'git://github.com/warpc/grit.git' #, :path => '~/Sites/code/grit' gem "grit", :git => 'git://github.com/warpc/grit.git' #, :path => '~/Sites/code/grit'
gem 'charlock_holmes', '~> 0.6.8' #, :git => 'git://github.com/brianmario/charlock_holmes.git', :branch => 'bundle-icu' gem 'charlock_holmes', '~> 0.6.8' #, :git => 'git://github.com/brianmario/charlock_holmes.git', :branch => 'bundle-icu'
# gem 'ruby-filemagic', '~> 0.4.2', :require => 'filemagic/ext'
gem 'github-linguist', '~> 2.1.2', :require => 'linguist'
gem 'diff-display', '~> 0.0.1' gem 'diff-display', '~> 0.0.1'
# Wiki # Wiki
@ -39,7 +41,7 @@ gem 'wikicloth'
gem 'unicorn', '~> 4.3.1', :platforms => [:mri, :rbx] gem 'unicorn', '~> 4.3.1', :platforms => [:mri, :rbx]
gem 'trinidad', '~> 1.0.2', :platforms => :jruby gem 'trinidad', '~> 1.0.2', :platforms => :jruby
gem 'newrelic_rpm', '~> 3.3.5', :platforms => [:mri, :rbx] gem 'newrelic_rpm', '~> 3.4.0.1', :platforms => [:mri, :rbx]
gem 'whenever', '~> 0.7.3', :require => false gem 'whenever', '~> 0.7.3', :require => false
gem 'jbuilder', '~> 0.4.0' gem 'jbuilder', '~> 0.4.0'
@ -54,14 +56,14 @@ gem 'rails-backbone', '~> 0.7.2'
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'
gem 'compass-rails', '~> 1.0.2' gem 'compass-rails', '~> 1.0.3'
gem 'uglifier', '~> 1.2.4' gem 'uglifier', '~> 1.2.4'
gem 'therubyracer', '~> 0.10.1', :platforms => [:mri, :rbx] gem 'therubyracer', '~> 0.10.1', :platforms => [:mri, :rbx]
gem 'therubyrhino', '~> 1.73.1', :platforms => :jruby gem 'therubyrhino', '~> 1.73.1', :platforms => :jruby
end end
group :production do group :production do
gem "airbrake", '~> 3.1.1' gem "airbrake", '~> 3.1.2'
gem 'bluepill', '~> 0.0.60', :require => false gem 'bluepill', '~> 0.0.60', :require => false
end end
@ -78,8 +80,8 @@ group :development do
end end
group :test do group :test do
gem 'rspec-rails', '~> 2.10.1', :group => 'development' gem 'rspec-rails', '~> 2.11.0', :group => 'development'
gem 'factory_girl_rails', '~> 3.4.0' gem 'factory_girl_rails', '~> 3.5.0'
gem 'rr', '~> 1.0.4' gem 'rr', '~> 1.0.4'
gem 'shoulda' gem 'shoulda'
end end

View File

@ -52,7 +52,7 @@ GEM
activesupport (3.2.6) activesupport (3.2.6)
i18n (~> 0.6) i18n (~> 0.6)
multi_json (~> 1.0) multi_json (~> 1.0)
airbrake (3.1.1) airbrake (3.1.2)
activesupport activesupport
builder builder
albino (1.3.3) albino (1.3.3)
@ -88,34 +88,41 @@ GEM
coffee-script-source coffee-script-source
execjs execjs
coffee-script-source (1.3.3) coffee-script-source (1.3.3)
compass (0.12.1) compass (0.12.2)
chunky_png (~> 1.2) chunky_png (~> 1.2)
fssm (>= 0.2.7) fssm (>= 0.2.7)
sass (~> 3.1) sass (~> 3.1)
compass-rails (1.0.2) compass-rails (1.0.3)
compass (>= 0.12.0, < 0.14) compass (>= 0.12.2, < 0.14)
creole (0.4.2) creole (0.4.2)
daemons (1.1.6) daemons (1.1.6)
devise (2.0.4) devise (2.1.2)
bcrypt-ruby (~> 3.0) bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.0.3) orm_adapter (~> 0.1)
railties (~> 3.1) railties (~> 3.1)
warden (~> 1.1.1) warden (~> 1.2.1)
diff-display (0.0.1) diff-display (0.0.1)
diff-lcs (1.1.3) diff-lcs (1.1.3)
ejs (1.0.0) ejs (1.0.0)
erubis (2.7.0) erubis (2.7.0)
escape_utils (0.2.4)
eventmachine (0.12.10) eventmachine (0.12.10)
execjs (1.4.0) execjs (1.4.0)
multi_json (~> 1.0) multi_json (~> 1.0)
expression_parser (0.9.0) expression_parser (0.9.0)
factory_girl (3.4.0) factory_girl (3.5.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
factory_girl_rails (3.4.0) factory_girl_rails (3.5.0)
factory_girl (~> 3.4.0) factory_girl (~> 3.5.0)
railties (>= 3.0.0) railties (>= 3.0.0)
ffi (1.0.11)
fssm (0.2.9) fssm (0.2.9)
github-markup (0.7.2) github-linguist (2.1.2)
charlock_holmes (~> 0.6.6)
escape_utils (~> 0.2.3)
mime-types (~> 1.18)
pygments.rb (>= 0.2.13)
github-markup (0.7.4)
gollum (1.3.1) gollum (1.3.1)
albino (~> 1.3.2) albino (~> 1.3.2)
github-markup (>= 0.4.0, < 1.0.0) github-markup (>= 0.4.0, < 1.0.0)
@ -132,18 +139,18 @@ GEM
haml (~> 3.0) haml (~> 3.0)
railties (~> 3.0) railties (~> 3.0)
hashie (1.2.0) hashie (1.2.0)
highline (1.6.12) highline (1.6.13)
hike (1.2.1) hike (1.2.1)
hirb (0.6.2) hirb (0.7.0)
i18n (0.6.0) i18n (0.6.0)
jbuilder (0.4.0) jbuilder (0.4.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
blankslate (>= 2.1.2.4) blankslate (>= 2.1.2.4)
journey (1.0.3) journey (1.0.4)
jquery-rails (2.0.2) jquery-rails (2.0.2)
railties (>= 3.2.0, < 5.0) railties (>= 3.2.0, < 5.0)
thor (~> 0.14) thor (~> 0.14)
json (1.7.3) json (1.7.4)
kgio (2.7.4) kgio (2.7.4)
libv8 (3.3.10.4) libv8 (3.3.10.4)
macaddr (1.6.1) macaddr (1.6.1)
@ -152,18 +159,18 @@ GEM
i18n (>= 0.4.0) i18n (>= 0.4.0)
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
mailcatcher (0.5.6) mailcatcher (0.5.8)
activesupport (~> 3.0) activesupport (~> 3.0)
eventmachine (~> 0.12) eventmachine (~> 0.12)
haml (~> 3.1) haml (~> 3.1)
mail (~> 2.3) mail (~> 2.3)
sinatra (~> 1.2) sinatra (~> 1.2)
skinny (~> 0.2) skinny (~> 0.2, >= 0.2.1)
sqlite3 (~> 1.3) sqlite3 (~> 1.3)
thin (~> 1.2) thin (~> 1.2)
meta-tags (1.2.6) meta-tags (1.2.6)
actionpack actionpack
mime-types (1.18) mime-types (1.19)
multi_json (1.3.6) multi_json (1.3.6)
mustache (0.99.4) mustache (0.99.4)
net-scp (1.0.4) net-scp (1.0.4)
@ -173,16 +180,16 @@ GEM
net-ssh (2.5.2) net-ssh (2.5.2)
net-ssh-gateway (1.1.0) net-ssh-gateway (1.1.0)
net-ssh (>= 1.99.1) net-ssh (>= 1.99.1)
newrelic_rpm (3.3.5) newrelic_rpm (3.4.0.1)
nokogiri (1.5.4) nokogiri (1.5.5)
omniauth (1.0.3) omniauth (1.1.0)
hashie (~> 1.2) hashie (~> 1.2)
rack rack
omniauth-openid (1.0.1) omniauth-openid (1.0.1)
omniauth (~> 1.0) omniauth (~> 1.0)
rack-openid (~> 1.3.1) rack-openid (~> 1.3.1)
orm_adapter (0.0.7) orm_adapter (0.4.0)
paperclip (3.0.4) paperclip (3.1.4)
activemodel (>= 3.0.0) activemodel (>= 3.0.0)
activerecord (>= 3.0.0) activerecord (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
@ -192,9 +199,11 @@ GEM
rails (~> 3.0) rails (~> 3.0)
redis redis
resque resque
pg (0.13.2) pg (0.14.0)
polyglot (0.3.3) polyglot (0.3.3)
posix-spawn (0.3.6) posix-spawn (0.3.6)
pygments.rb (0.2.13)
rubypython (~> 0.5.3)
rack (1.4.1) rack (1.4.1)
rack-cache (1.2) rack-cache (1.2)
rack (>= 0.4) rack (>= 0.4)
@ -230,21 +239,21 @@ GEM
rake (>= 0.8.7) rake (>= 0.8.7)
rdoc (~> 3.4) rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0) thor (>= 0.14.6, < 2.0)
raindrops (0.9.0) raindrops (0.10.0)
rake (0.9.2.2) rake (0.9.2.2)
rdiscount (1.6.8) rdiscount (1.6.8)
rdoc (3.12) rdoc (3.12)
json (~> 1.4) json (~> 1.4)
redcarpet (1.17.2) redcarpet (1.17.2)
redis (2.2.2) redis (3.0.1)
redis-namespace (1.0.3) redis-namespace (1.2.0)
redis (< 3.0.0) redis (~> 3.0.0)
redisk (0.2.2) redisk (0.2.2)
redis (>= 0.1.1) redis (>= 0.1.1)
redis-namespace (>= 0.1.0) redis-namespace (>= 0.1.0)
resque (1.20.0) resque (1.21.0)
multi_json (~> 1.0) multi_json (~> 1.0)
redis-namespace (~> 1.0.2) redis-namespace (~> 1.0)
sinatra (>= 0.9.2) sinatra (>= 0.9.2)
vegas (~> 0.1.2) vegas (~> 0.1.2)
resque-status (0.3.3) resque-status (0.3.3)
@ -254,46 +263,50 @@ GEM
resque_mailer (2.1.0) resque_mailer (2.1.0)
actionmailer (~> 3.0) actionmailer (~> 3.0)
rr (1.0.4) rr (1.0.4)
rspec (2.10.0) rspec (2.11.0)
rspec-core (~> 2.10.0) rspec-core (~> 2.11.0)
rspec-expectations (~> 2.10.0) rspec-expectations (~> 2.11.0)
rspec-mocks (~> 2.10.0) rspec-mocks (~> 2.11.0)
rspec-core (2.10.1) rspec-core (2.11.1)
rspec-expectations (2.10.0) rspec-expectations (2.11.2)
diff-lcs (~> 1.1.3) diff-lcs (~> 1.1.3)
rspec-mocks (2.10.1) rspec-mocks (2.11.1)
rspec-rails (2.10.1) rspec-rails (2.11.0)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
railties (>= 3.0) railties (>= 3.0)
rspec (~> 2.10.0) rspec (~> 2.11.0)
ruby-haml-js (0.0.3) ruby-haml-js (0.0.3)
execjs execjs
sprockets (>= 2.0.0) sprockets (>= 2.0.0)
ruby-openid (2.1.8) ruby-openid (2.2.0)
rubypython (0.5.3)
blankslate (>= 2.1.2.3)
ffi (~> 1.0.7)
russian (0.6.0) russian (0.6.0)
i18n (>= 0.5.0) i18n (>= 0.5.0)
rvm-capistrano (1.2.2) rvm-capistrano (1.2.5)
capistrano (>= 2.0.0) capistrano (>= 2.0.0)
sanitize (2.0.3) sanitize (2.0.3)
nokogiri (>= 1.4.4, < 1.6) nokogiri (>= 1.4.4, < 1.6)
sass (3.1.19) sass (3.1.20)
sass-rails (3.2.5) sass-rails (3.2.5)
railties (~> 3.2.0) railties (~> 3.2.0)
sass (>= 3.1.10) sass (>= 3.1.10)
tilt (~> 1.3) tilt (~> 1.3)
shotgun (0.9) shotgun (0.9)
rack (>= 1.0) rack (>= 1.0)
shoulda (3.0.1) shoulda (3.1.1)
shoulda-context (~> 1.0.0) shoulda-context (~> 1.0)
shoulda-matchers (~> 1.0.0) shoulda-matchers (~> 1.2)
shoulda-context (1.0.0) shoulda-context (1.0.0)
shoulda-matchers (1.0.0) shoulda-matchers (1.2.0)
activesupport (>= 3.0.0)
sinatra (1.3.2) sinatra (1.3.2)
rack (~> 1.3, >= 1.3.6) rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2) rack-protection (~> 1.2)
tilt (~> 1.3, >= 1.3.3) tilt (~> 1.3, >= 1.3.3)
skinny (0.2.0) skinny (0.2.1)
eventmachine (~> 0.12) eventmachine (~> 0.12)
thin (~> 1.2) thin (~> 1.2)
sprockets (2.1.3) sprockets (2.1.3)
@ -302,22 +315,22 @@ GEM
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6) sqlite3 (1.3.6)
state_machine (1.1.2) state_machine (1.1.2)
systemu (2.5.1) systemu (2.5.2)
therubyracer (0.10.1) therubyracer (0.10.1)
libv8 (~> 3.3.10) libv8 (~> 3.3.10)
thin (1.3.1) thin (1.4.1)
daemons (>= 1.0.9) daemons (>= 1.0.9)
eventmachine (>= 0.12.6) eventmachine (>= 0.12.6)
rack (>= 1.0.0) rack (>= 1.0.0)
thor (0.15.2) thor (0.15.4)
tilt (1.3.3) tilt (1.3.3)
treetop (1.4.10) treetop (1.4.10)
polyglot polyglot
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
tzinfo (0.3.33) tzinfo (0.3.33)
uglifier (1.2.4) uglifier (1.2.6)
execjs (>= 0.3.0) execjs (>= 0.3.0)
multi_json (>= 1.0.2) multi_json (~> 1.3)
unicorn (4.3.1) unicorn (4.3.1)
kgio (~> 2.6) kgio (~> 2.6)
rack rack
@ -326,7 +339,7 @@ GEM
macaddr (~> 1.0) macaddr (~> 1.0)
vegas (0.1.11) vegas (0.1.11)
rack (>= 1.0.0) rack (>= 1.0.0)
warden (1.1.1) warden (1.2.1)
rack (>= 1.0) rack (>= 1.0)
whenever (0.7.3) whenever (0.7.3)
activesupport (>= 2.3.4) activesupport (>= 2.3.4)
@ -341,20 +354,21 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
RedCloth RedCloth
airbrake (~> 3.1.1) airbrake (~> 3.1.2)
ancestry (~> 1.3.0) ancestry (~> 1.3.0)
bluepill (~> 0.0.60) bluepill (~> 0.0.60)
cancan (~> 1.6.7) cancan (= 1.6.7)
cape cape
capistrano capistrano
capistrano_colors capistrano_colors
charlock_holmes (~> 0.6.8) charlock_holmes (~> 0.6.8)
coffee-rails (~> 3.2.2) coffee-rails (~> 3.2.2)
compass-rails (~> 1.0.2) compass-rails (~> 1.0.3)
creole creole
devise (~> 2.0.4) devise (~> 2.1.2)
diff-display (~> 0.0.1) diff-display (~> 0.0.1)
factory_girl_rails (~> 3.4.0) factory_girl_rails (~> 3.5.0)
github-linguist (~> 2.1.2)
gollum (= 1.3.1) gollum (= 1.3.1)
grack! grack!
grit! grit!
@ -365,12 +379,12 @@ DEPENDENCIES
jquery-rails (~> 2.0.2) jquery-rails (~> 2.0.2)
mailcatcher mailcatcher
meta-tags (~> 1.2.5) meta-tags (~> 1.2.5)
newrelic_rpm (~> 3.3.5) newrelic_rpm (~> 3.4.0.1)
omniauth (~> 1.0.3) omniauth (~> 1.1.0)
omniauth-openid (~> 1.0.1) omniauth-openid (~> 1.0.1)
paperclip (~> 3.0.4) paperclip (~> 3.1.4)
perform_later (~> 1.3.0) perform_later (~> 1.3.0)
pg (~> 0.13.2) pg (~> 0.14.0)
rails (= 3.2.6) rails (= 3.2.6)
rails-backbone (~> 0.7.2) rails-backbone (~> 0.7.2)
rails3-generators rails3-generators
@ -378,11 +392,11 @@ DEPENDENCIES
rdiscount rdiscount
redcarpet (= 1.17.2) redcarpet (= 1.17.2)
redhillonrails_core! redhillonrails_core!
resque (~> 1.20.0) resque (~> 1.21.0)
resque-status (~> 0.3.3) resque-status (~> 0.3.3)
resque_mailer (~> 2.1.0) resque_mailer (~> 2.1.0)
rr (~> 1.0.4) rr (~> 1.0.4)
rspec-rails (~> 2.10.1) rspec-rails (~> 2.11.0)
ruby-haml-js (~> 0.0.3) ruby-haml-js (~> 0.0.3)
russian (~> 0.6.0) russian (~> 0.6.0)
rvm-capistrano rvm-capistrano

View File

@ -0,0 +1,18 @@
function setCookie (name, value, expires, path, domain, secure) {
document.cookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
}
$(document).ready(function() {
if ($(".alert").size()) {
$(".alert").alert()
}
$('#close-alert').click(function () {
setCookie("flash_notify_hash", FLASH_HASH_ID, FLASH_EXPIRES_AT);
});
});

View File

@ -1201,4 +1201,64 @@ hr.bootstrap {
.line_numbers a { .line_numbers a {
color: #999999; color: #999999;
} }
/* Flash Notifies */
.flash_notify {
.alert-success {
color: #468847;
background-color: #DFF0D8;
border-color: #D6E9C6;
}
.alert {
padding: 8px 35px 8px 14px;
margin-bottom: 18px;
color: #C09853;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
background-color: #FCF8E3;
border: 1px solid #FBEED5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.alert-danger, .alert-error {
color: #B94A48;
background-color: #F2DEDE;
border-color: #EED3D7;
}
.alert-info {
color: #3A87AD;
background-color: #D9EDF7;
border-color: #BCE8F1;
}
.alert .close {
position: relative;
top: -2px;
right: -21px;
line-height: 18px;
}
button.close {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
}
.close {
float: right;
font-size: 20px;
font-weight: bold;
line-height: 18px;
color: black;
text-shadow: 0 1px 0 white;
opacity: 0.2;
filter: alpha(opacity=20);
}
}

View File

@ -0,0 +1,41 @@
class Admin::FlashNotifiesController < Admin::BaseController
def index
@flash_notifies = FlashNotify.paginate(:page => params[:page], :per_page => 20)
end
def new
@flash_notify = FlashNotify.new(:published => true)
end
def create
@flash_notify = FlashNotify.new(params[:flash_notify])
if @flash_notify.save
flash[:notice] = t("flash.flash_notify.saved")
redirect_to admin_flash_notifies_path
else
flash[:error] = t("flash.flash_notify.save_error")
flash[:warning] = @flash_notify.errors.full_messages.join('. ')
render :new
end
end
def update
if @flash_notify.update_attributes(params[:flash_notify])
flash[:notice] = t("flash.flash_notify.saved")
redirect_to admin_flash_notifies_path
else
flash[:error] = t("flash.flash_notify.save_error")
flash[:warning] = @flash_notify.errors.full_messages.join('. ')
render :edit
end
end
def destroy
if @flash_notify.destroy
flash[:notice] = t("flash.flash_notify.destroyed")
else
flash[:error] = t("flash.flash_notify.destroy_error")
end
redirect_to admin_flash_notifies_path
end
end

View File

@ -12,7 +12,7 @@ class Admin::UsersController < Admin::BaseController
def create def create
@user.role = params[:role] @user.role = params[:role]
@user.confirmed_at = Time.now.utc @user.confirmed_at = Time.now.utc
if @user.save if (@user.save rescue false)
flash[:notice] = t('flash.user.saved') flash[:notice] = t('flash.user.saved')
redirect_to admin_users_path redirect_to admin_users_path
else else

View File

@ -17,6 +17,7 @@ class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception| rescue_from CanCan::AccessDenied do |exception|
redirect_to forbidden_url, :alert => t("flash.exception_message") redirect_to forbidden_url, :alert => t("flash.exception_message")
end end
rescue_from Grit::NoSuchPathError, :with => :not_found
protected protected
@ -53,4 +54,8 @@ class ApplicationController < ActionController::Base
"application" "application"
end end
end end
def not_found
raise ActionController::RoutingError.new('Not Found')
end
end end

View File

@ -46,7 +46,8 @@ class Projects::BuildListsController < Projects::BaseController
Arch.where(:id => params[:arches]).each do |arch| Arch.where(:id => params[:arches]).each do |arch|
Platform.main.where(:id => params[:build_for_platforms]).each do |build_for_platform| Platform.main.where(:id => params[:build_for_platforms]).each do |build_for_platform|
@build_list = @project.build_lists.build(params[:build_list]) @build_list = @project.build_lists.build(params[:build_list])
@build_list.commit_hash = @project.git_repository.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last || @build_list.project_version).first.id if @build_list.project_version @build_list.commit_hash = @project.repo.commits(@build_list.project_version.match(/^latest_(.+)/).to_a.last ||
@build_list.project_version).first.id if @build_list.project_version
@build_list.build_for_platform = build_for_platform; @build_list.arch = arch; @build_list.user = current_user @build_list.build_for_platform = build_for_platform; @build_list.arch = arch; @build_list.user = current_user
@build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.build_for_platform.repository_ids.include? ir.to_i} @build_list.include_repos = @build_list.include_repos.select {|ir| @build_list.build_for_platform.repository_ids.include? ir.to_i}
@build_list.priority = current_user.build_priority # User builds more priority than mass rebuild with zero priority @build_list.priority = current_user.build_priority # User builds more priority than mass rebuild with zero priority
@ -98,7 +99,6 @@ class Projects::BuildListsController < Projects::BaseController
else else
@build_list.fail_publish @build_list.fail_publish
end end
render :nothing => true, :status => 200 render :nothing => true, :status => 200
end end

View File

@ -41,7 +41,7 @@ class Projects::CommentsController < Projects::BaseController
def find_commentable def find_commentable
@commentable = params[:issue_id].present? && @project.issues.find_by_serial_id(params[:issue_id]) || @commentable = params[:issue_id].present? && @project.issues.find_by_serial_id(params[:issue_id]) ||
params[:commit_id].present? && @project.git_repository.commit(params[:commit_id]) params[:commit_id].present? && @project.repo.commit(params[:commit_id])
end end
def find_or_build_comment def find_or_build_comment

View File

@ -25,7 +25,7 @@ class Projects::CommitSubscribesController < Projects::BaseController
protected protected
def find_commit def find_commit
@commit = @project.git_repository.commit(params[:commit_id]) @commit = @project.repo.commit(params[:commit_id])
@options = {:project_id => @project.id, :subscribeable_id => @commit.id.hex, :subscribeable_type => @commit.class.name, :user_id => current_user.id} @options = {:project_id => @project.id, :subscribeable_id => @commit.id.hex, :subscribeable_type => @commit.class.name, :user_id => current_user.id}
end end
end end

View File

@ -4,36 +4,19 @@ class Projects::Git::BaseController < Projects::BaseController
skip_before_filter :authenticate_user!, :only => [:show, :index, :blame, :raw, :archive] if APP_CONFIG['anonymous_access'] skip_before_filter :authenticate_user!, :only => [:show, :index, :blame, :raw, :archive] if APP_CONFIG['anonymous_access']
load_and_authorize_resource :project load_and_authorize_resource :project
before_filter :find_git_repository before_filter :set_treeish_and_path
before_filter :find_tags before_filter :set_branch_and_tree
before_filter :find_branches
before_filter :set_treeish
before_filter :set_current_tag
before_filter :set_current_branch
protected protected
def find_git_repository def set_treeish_and_path
@git_repository = @project.git_repository
end
def find_tags
@tags = @git_repository.tags
end
def find_branches
@branches = @git_repository.branches
end
def set_treeish
@treeish = params[:treeish].presence || @project.default_branch @treeish = params[:treeish].presence || @project.default_branch
@path = params[:path]
end end
def set_current_tag def set_branch_and_tree
@current_tag = @tags.select{|t| t.name == @treeish }.first @branch = @project.repo.branches.detect{|b| b.name == @treeish}
end @tree = @project.repo.tree(@treeish)
# raise Grit::NoSuchPathError if @tree.blobs.blank?
def set_current_branch
@current_branch = @branches.select{|b| b.name == @treeish }.first
end end
end end

View File

@ -1,34 +1,17 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Projects::Git::BlobsController < Projects::Git::BaseController class Projects::Git::BlobsController < Projects::Git::BaseController
before_filter :find_tree before_filter :set_blob
before_filter :find_branch before_filter lambda {authorize! :write, @project}, :only => [:edit, :update]
before_filter :set_path_blob
def show def show
redirect_to project_path(@project) and return unless @blob.present?
if params[:raw]
response.headers['Cache-Control'] = "public, max-age=#{12.hours.to_i}"
response.headers['Content-Type'] = @blob.mime_type
response.headers['Content-Disposition'] = 'inline'
render(:text => @blob.data) and return
end
end end
def edit def edit
redirect_to project_path(@project) and return unless @blob.present?
authorize! :write, @project
end end
def update def update
redirect_to project_path(@project) and return unless @blob.present? if @project.update_file(params[:path], params[:content].gsub("\r", ''),
authorize! :write, @project :message => params[:message].gsub("\r", ''), :actor => current_user, :head => @treeish)
# Here might be callbacks for notification purposes:
# @git_repository.after_update_file do |repo, sha|
# end
res = @git_repository.update_file(params[:path], params[:content].gsub("\r", ''),
:message => params[:message].gsub("\r", ''), :actor => current_user, :head => @treeish)
if res
flash[:notice] = t("flash.blob.successfully_updated", :name => params[:path]) flash[:notice] = t("flash.blob.successfully_updated", :name => params[:path])
else else
flash[:notice] = t("flash.blob.updating_error", :name => params[:path]) flash[:notice] = t("flash.blob.updating_error", :name => params[:path])
@ -37,28 +20,17 @@ class Projects::Git::BlobsController < Projects::Git::BaseController
end end
def blame def blame
@blame = Grit::Blob.blame(@git_repository.repo, @commit.id, @path) @blame = Grit::Blob.blame(@project.repo, @commit.id, @path)
end end
def raw def raw
redirect_to project_path(@project) and return unless @blob.present? send_data @blob.data, :type => @blob.content_type, :disposition => @blob.disposition
headers["Content-Disposition"] = %[attachment;filename="#{@blob.name}"]
render :text => @blob.data, :content_type => @blob.mime_type
end end
protected protected
def find_branch def set_blob
@branch = @project.branch(@treeish) @blob = @tree / @path or raise Grit::NoSuchPathError
end @commit = @project.repo.log(@treeish, @path, :max_count => 1).first
def set_path_blob
@path = params[:path]
@blob = @tree / @path
@commit = @git_repository.log(@treeish, @path, :max_count => 1).first
end
def find_tree
@tree = @git_repository.tree(@treeish)
end end
end end

View File

@ -1,23 +1,15 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Projects::Git::CommitsController < Projects::Git::BaseController class Projects::Git::CommitsController < Projects::Git::BaseController
def index def index
@branch_name = params[:treeish] || @project.default_branch
@branch = @project.branch(@branch_name)
@path = params[:path]
if @path.present? if @path.present?
@commits = @git_repository.repo.log(@branch_name, @path) @commits = @project.repo.log(@treeish, @path)
@render_paginate = false
else else
@commits, @page, @last_page = @git_repository.paginate_commits(@branch_name, :page => params[:page]) @commits, @page, @last_page = @project.paginate_commits(@treeish, :page => params[:page])
@render_paginate = true
end end
end end
def show def show
@commit = @git_repository.commit(params[:id]) # @git_repository.commits(params[:id]).first @commit = @project.repo.commit(params[:id])
respond_to do |format| respond_to do |format|
format.html format.html
format.diff { render :text => (@commit.diffs.map(&:diff).join("\n") rescue ''), :content_type => "text/plain" } format.diff { render :text => (@commit.diffs.map(&:diff).join("\n") rescue ''), :content_type => "text/plain" }

View File

@ -1,32 +1,21 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Projects::Git::TreesController < Projects::Git::BaseController class Projects::Git::TreesController < Projects::Git::BaseController
before_filter lambda{redirect_to @project if params[:treeish] == @project.default_branch and params[:path].blank?}, :only => 'show'
def show def show
redirect_to project_path(@project) and return if params[:treeish] == @project.default_branch and params[:path].blank? @tree = @tree / @path if @path.present?
@commit = @branch.present? ? @branch.commit() : @project.repo.log(@treeish, @path, :max_count => 1).first
@path = params[:path] render 'empty' unless @commit
@tree = @git_repository.tree(@treeish)
@branch = @project.branch(@treeish)
# @commit = @git_repository.commits(@treeish, 1).first
# Raises Grit::Git::GitTimeout
@commit = @branch.present? ? @branch.commit() : @git_repository.log(@treeish, @path, :max_count => 1).first
render "empty" and return unless @commit
@tree = @tree / @path if @path
end end
def archive def archive
treeish = params[:treeish].presence || @project.default_branch @commit = @project.repo.log(@treeish, nil, :max_count => 1).first
format = params[:format] || 'tar' raise Grit::NoSuchPathError unless @commit
commit = @project.git_repository.log(treeish, nil, :max_count => 1).first name = "#{@project.owner.uname}-#{@project.name}#{@project.repo.tags.include?(@treeish) ? "-#{@treeish}" : ''}-#{@commit.id[0..19]}"
if !commit or !['tar', 'zip'].include?(format) fullname = "#{name}.#{params[:format] == 'tar' ? 'tar.gz' : 'zip'}"
raise ActiveRecord::RecordNotFound#("Couldn't send Project archive with id=#{@project.id}, treeish=#{treeish} and format=#{format}")
end
name = "#{@project.owner.uname}-#{@project.name}#{@project.tags.include?(treeish) ? "-#{treeish}" : ''}-#{commit.id[0..19]}"
fullname = "#{name}.#{format == 'tar' ? 'tar.gz' : 'zip'}"
file = Tempfile.new fullname, 'tmp' file = Tempfile.new fullname, 'tmp'
system("cd #{@project.path}; git archive --format=#{format} --prefix=#{name}/ #{treeish} #{format == 'tar' ? ' | gzip -9' : ''} > #{file.path}") system("cd #{@project.path}; git archive --format=#{params[:format]} --prefix=#{name}/ #{@treeish} #{params[:format] == 'tar' ? ' | gzip -9' : ''} > #{file.path}")
file.close file.close
send_file file.path, :disposition => 'attachment', :type => "application/#{format == 'tar' ? 'x-tar-gz' : 'zip'}", :filename => fullname send_file file.path, :disposition => 'attachment', :type => "application/#{params[:format] == 'tar' ? 'x-tar-gz' : 'zip'}", :filename => fullname
end end
end end

View File

@ -1,11 +1,7 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class Projects::ProjectsController < Projects::BaseController class Projects::ProjectsController < Projects::BaseController
before_filter :authenticate_user! before_filter :authenticate_user!
load_and_authorize_resource load_and_authorize_resource :id_param => :project_name # to force member actions load
# TODO WTF ? fork, update, sections not authorize
before_filter do |controller|
authorize! params[:action].to_sym, @project if params[:action] != 'index'
end
def index def index
@projects = Project.accessible_by(current_ability, :membered) @projects = Project.accessible_by(current_ability, :membered)

View File

@ -94,8 +94,7 @@ class Projects::PullRequestsController < Projects::BaseController
#Maybe slow? ILIKE? #Maybe slow? ILIKE?
items = Project.accessible_by(current_ability, :membered) items = Project.accessible_by(current_ability, :membered)
items << PullRequest.default_base_project(@project) items << PullRequest.default_base_project(@project)
logger.debug "items.count is #{items.count}" items.select! {|e| Regexp.new(params[:term].downcase).match(e.name.downcase) && e.repo.branches.count > 0}
items.select! {|e| Regexp.new(params[:term].downcase).match(e.name.downcase) && e.branches.count > 0}
items.uniq! items.uniq!
render :json => json_for_autocomplete_base(items)#, :full_name, [:branches]) render :json => json_for_autocomplete_base(items)#, :full_name, [:branches])
@ -110,7 +109,7 @@ class Projects::PullRequestsController < Projects::BaseController
def json_for_autocomplete_base items def json_for_autocomplete_base items
items.collect do |project| items.collect do |project|
hash = {"id" => project.id.to_s, "label" => project.full_name, "value" => project.full_name} hash = {"id" => project.id.to_s, "label" => project.full_name, "value" => project.full_name}
hash[:refs] = project.branches_and_tags.map &:name hash[:refs] = project.repo.branches_and_tags.map &:name
hash hash
end end
end end

View File

@ -4,7 +4,7 @@ module GitHelper
def render_path def render_path
# TODO: Looks ugly, rewrite with clear mind. # TODO: Looks ugly, rewrite with clear mind.
if @path.present? if @path.present?
if @treeish == "master" if @treeish == @project.default_branch
res = "#{link_to @project.name, tree_path(@project)} / " res = "#{link_to @project.name, tree_path(@project)} / "
else else
res = "#{link_to @project.name, tree_path(@project, @treeish)} / " res = "#{link_to @project.name, tree_path(@project, @treeish)} / "
@ -36,22 +36,6 @@ module GitHelper
res.html_safe res.html_safe
end end
def render_blob(blob)
blob.data.split("\n").collect do |line|
content_tag :div, line.present? ? h(line) : tag(:br)
end.join.html_safe
end
def choose_render_way(blob)
case
when blob.mime_type.match(/image/); :image
when blob.binary?; :binary
else
@text = @blob.data.split("\n")
:text
end
end
def iterate_path(path, &block) def iterate_path(path, &block)
path.split(File::SEPARATOR).inject('') do |a, e| path.split(File::SEPARATOR).inject('') do |a, e|
if e != '.' and e != '..' if e != '.' and e != '..'
@ -63,7 +47,6 @@ module GitHelper
end end
end end
# TODO This is very dirty hack. Maybe need to be changed.
def branch_selector_options(project) def branch_selector_options(project)
p = params.dup p = params.dup
p.delete(:path) if p[:path].present? # to root path p.delete(:path) if p[:path].present? # to root path
@ -71,15 +54,21 @@ module GitHelper
current = url_for(p).split('?', 2).first current = url_for(p).split('?', 2).first
res = [] res = []
res << [I18n.t('layout.git.repositories.commits'), [truncate(params[:treeish], :length => 20)]] unless (project.branches + project.tags).map(&:name).include?(params[:treeish] || project.default_branch) res << [I18n.t('layout.git.repositories.commits'), [params[:treeish].truncate(20)]] unless project.repo.branches_and_tags.map(&:name).include?(params[:treeish] || project.default_branch)
res << [I18n.t('layout.git.repositories.branches'), project.branches.map{|b| [truncate(b.name, :length => 20), url_for(p.merge :treeish => b.name).split('?', 2).first]}] linking = Proc.new {|t| [t.name.truncate(20), url_for(p.merge :treeish => t.name).split('?', 2).first]}
res << [I18n.t('layout.git.repositories.tags'), project.tags.map{|t| [truncate(t.name, :length => 20), url_for(p.merge :treeish => t.name).split('?', 2).first]}] res << [I18n.t('layout.git.repositories.branches'), project.repo.branches.map(&linking)]
res << [I18n.t('layout.git.repositories.tags'), project.repo.tags.map(&linking)]
grouped_options_for_select(res, current) grouped_options_for_select(res, current)
end end
def versions_for_group_select(project)
[ ['Branches', project.repo.branches.map{|b| "latest_#{b.name}"}],
['Tags', project.repo.tags.map(&:name)] ]
end
def split_commits_by_date(commits) def split_commits_by_date(commits)
res = commits.sort{|x, y| y.authored_date <=> x.authored_date}.inject({}) do |h, commit| commits.sort{|x, y| y.authored_date <=> x.authored_date}.inject({}) do |h, commit|
dt = commit.authored_date dt = commit.authored_date
h[dt.year] ||= {} h[dt.year] ||= {}
h[dt.year][dt.month] ||= {} h[dt.year][dt.month] ||= {}
@ -87,7 +76,5 @@ module GitHelper
h[dt.year][dt.month][dt.day] << commit h[dt.year][dt.month][dt.day] << commit
h h
end end
return res
end end
end end

View File

@ -37,7 +37,7 @@ module PullRequestHelper
end end
def ref_path project, ref def ref_path project, ref
return tree_path(project, ref) if project.branches_and_tags.map(&:name).include? ref return tree_path(project, ref) if project.repo.branches_and_tags.map(&:name).include? ref
return commit_path(project, ref) if project.git_repository.commit ref return commit_path(project, ref) if project.git_repository.commit ref
'#' '#'
end end

View File

@ -74,7 +74,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
change_type = record.change_type change_type = record.change_type
branch_name = record.refname.split('/').last branch_name = record.refname.split('/').last
last_commits = record.project.git_repository.repo.log(branch_name, nil).first(3) last_commits = record.project.repo.log(branch_name, nil).first(3)
first_commiter = User.find_by_email(last_commits[0].author.email) unless last_commits.blank? first_commiter = User.find_by_email(last_commits[0].author.email) unless last_commits.blank?
last_commits = last_commits.collect do |commit| #:author => 'author' last_commits = last_commits.collect do |commit| #:author => 'author'
[commit.sha, commit.message] [commit.sha, commit.message]
@ -87,7 +87,7 @@ class ActivityFeedObserver < ActiveRecord::Observer
else else
kind = 'git_new_push_notification' kind = 'git_new_push_notification'
options = {:project_id => record.project.id, :project_name => record.project.name, :last_commits => last_commits, :branch_name => branch_name, options = {:project_id => record.project.id, :project_name => record.project.name, :last_commits => last_commits, :branch_name => branch_name,
:change_type => change_type, :user_email => record.project.git_repository.repo.log(branch_name, nil).first.author.email, :change_type => change_type, :user_email => record.project.repo.repo.log(branch_name, nil).first.author.email,
:project_owner => record.project.owner.uname} :project_owner => record.project.owner.uname}
options.merge!({:user_id => first_commiter.id, :user_name => first_commiter.name}) if first_commiter options.merge!({:user_id => first_commiter.id, :user_name => first_commiter.name}) if first_commiter
end end

View File

@ -189,7 +189,7 @@ class BuildList < ActiveRecord::Base
# TODO: remove 'return' after deployment ABF kernel 2.0 # TODO: remove 'return' after deployment ABF kernel 2.0
return if pkg.nil? # For old client that does not sends data about packages return if pkg.nil? # For old client that does not sends data about packages
self.package_version = "#{pkg.platform.name}-#{pkg.version}-#{pkg.release}" self.package_version = "#{pkg.platform.name}-#{pkg.version}-#{pkg.release}"
system("cd #{self.project.git_repository.path} && git tag #{self.package_version} #{self.commit_hash}") # TODO REDO through grit system("cd #{self.project.repo.path} && git tag #{self.package_version} #{self.commit_hash}") # TODO REDO through grit
save save
end end

View File

@ -20,15 +20,7 @@ class BuildList::Filter
build_lists = build_lists.scoped_to_is_circle(@options[:is_circle]) if @options[:is_circle].present? build_lists = build_lists.scoped_to_is_circle(@options[:is_circle]) if @options[:is_circle].present?
build_lists = build_lists.scoped_to_project_name(@options[:project_name]) if @options[:project_name] build_lists = build_lists.scoped_to_project_name(@options[:project_name]) if @options[:project_name]
build_lists = build_lists.by_mass_build(@options[:mass_build_id]) if @options[:mass_build_id] build_lists = build_lists.by_mass_build(@options[:mass_build_id]) if @options[:mass_build_id]
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end]) if @options[:updated_at_start] || @options[:updated_at_end]
# TODO [BuildList#created_at filters] Uncomment here and in build_lists/_filter.html.haml to return filters
#
# if @options[:created_at_start] || @options[:created_at_end]
# build_lists = build_lists.for_creation_date_period(@options[:created_at_start], @options[:created_at_end])
# end
if @options[:updated_at_start] || @options[:updated_at_end]
build_lists = build_lists.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
end
end end
build_lists build_lists
@ -49,8 +41,6 @@ class BuildList::Filter
@options = HashWithIndifferentAccess.new(options.reverse_merge({ @options = HashWithIndifferentAccess.new(options.reverse_merge({
:ownership => nil, :ownership => nil,
:status => nil, :status => nil,
:created_at_start => nil,
:created_at_end => nil,
:updated_at_start => nil, :updated_at_start => nil,
:updated_at_end => nil, :updated_at_end => nil,
:arch_id => nil, :arch_id => nil,
@ -63,14 +53,12 @@ class BuildList::Filter
})) }))
@options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'index' : 'owned') @options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'index' : 'owned')
@options[:status] = @options[:status].present? ? @options[:status].to_i : nil @options[:status] = @options[:status].try(:to_i)
@options[:created_at_start] = build_date_from_params(:created_at_start, @options)
@options[:created_at_end] = build_date_from_params(:created_at_end, @options)
@options[:updated_at_start] = build_date_from_params(:updated_at_start, @options) @options[:updated_at_start] = build_date_from_params(:updated_at_start, @options)
@options[:updated_at_end] = build_date_from_params(:updated_at_end, @options) @options[:updated_at_end] = build_date_from_params(:updated_at_end, @options)
@options[:project_version] = @options[:project_version].presence @options[:project_version] = @options[:project_version].presence
@options[:arch_id] = @options[:arch_id].present? ? @options[:arch_id].to_i : nil @options[:arch_id] = @options[:arch_id].try(:to_i)
@options[:platform_id] = @options[:platform_id].present? ? @options[:platform_id].to_i : nil @options[:platform_id] = @options[:platform_id].try(:to_i)
@options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil @options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil
@options[:bs_id] = @options[:bs_id].presence @options[:bs_id] = @options[:bs_id].presence
@options[:project_name] = @options[:project_name].presence @options[:project_name] = @options[:project_name].presence

View File

@ -15,7 +15,9 @@ class Comment < ActiveRecord::Base
attr_accessible :body attr_accessible :body
def commentable def commentable
commit_comment? ? project.git_repository.commit(commentable_id.to_s(16)) : super # raise commentable_id.inspect
# raise commentable_id.to_s(16).inspect
commit_comment? ? project.repo.commit(commentable_id.to_s(16)) : super # TODO leading zero problem
end end
def commentable=(c) def commentable=(c)

View File

@ -0,0 +1,24 @@
require 'digest/md5'
class FlashNotify < ActiveRecord::Base
# attr_accessible :title, :body
STATUSES = %w[error success info]
validates :status, :inclusion => {:in => STATUSES}
validates :body_ru, :body_en, :status, :presence => true
scope :published, where(:published => true)
def hash_id
@digest ||= Digest::MD5.hexdigest("#{self.id}-#{self.updated_at}")
end
def body(language)
read_attribute("body_#{language}")
end
def should_show?(cookie_hash_id)
cookie_hash_id != hash_id && published
end
end

View File

@ -1,130 +0,0 @@
# -*- encoding : utf-8 -*-
class Git::Repository
delegate :commits, :commit, :tree, :tags, :heads, :commit_count, :log, :branches, :to => :repo
attr_accessor :path, :name, :repo, :last_actor
def initialize(path)
@path = path
@update_callbacks = []
end
def master
commits('master', 1).first
end
def to_s
name
end
def repo
@repo ||= Grit::Repo.new(path) rescue Grit::Repo.new(GAP_REPO_PATH)
end
# Adds a callback to be fired after update file.
#
# block - A block that expects this Git::Repository instance and the created
# commit's SHA1 as the arguments.
#
# For example:
#
# after_update_file do |repo, sha|
# # callback body
# end
#
# Returns nothing.
def after_update_file(&block)
@update_callbacks << block
end
# Writes file to repo and runs 'after_update_file' callbacks
#
# path - path to file in repository
# data - new content of file
# options - an optional Hash of options
# :head - branch name to write this commit to
# (Default: 'master')
# :actor - author of this commit. (See Git::Repository#get_actor)
# (Default: nil)
# :message - commit message
# (Default: "Updated file <filename>")
#
# Returns commits sha if committing was successful and false otherwise
def update_file(path, data, options = {})
head = options[:head].to_s || 'master'
actor = get_actor(options[:actor])
filename = File.split(path).last
message = options[:message]
message = "Updated file #{filename}" if message.nil? or message.empty?
# can not write to unexisted branch
return false if branches.select{|b| b.name == head}.size != 1
parent = commits(head).first
index = repo.index
index.read_tree(parent.tree.id)
# can not create new file
return false if (index.current_tree / path).nil?
index.add(path, data)
sha = index.commit(message, :parents => [parent], :actor => actor,
:last_tree => parent.tree.id, :head => head)
# call all defined callbacks
@update_callbacks.each do |cb|
cb.call(self, sha)
end
sha
end
def self.create(path)
repo = Grit::Repo.init_bare(path)
repo.enable_daemon_serve
end
def paginate_commits(treeish, options = {})
options[:page] = 1 unless options[:page].present?
options[:page] = options[:page].to_i
options[:per_page] = 20 unless options[:per_page].present?
options[:per_page] = options[:per_page].to_i
skip = options[:per_page] * (options[:page] - 1)
last_page = (skip + options[:per_page]) >= commit_count(treeish)
[commits(treeish, options[:per_page], skip), options[:page], last_page]
end
# Pretty object inspection
def inspect
%Q{#<Git::Repository "#{@path}">}
end
protected
# Creates new Grit::Actor instance
#
# Might be:
# * A Hash containing :name and :email
# * An instance of Grit::Actor
# * A String like "John Doe <j.doe@example.com>
# * Any object that responds to `name` and `email` methods
def get_actor(actor = nil)
@last_actor = case actor.class.to_s
when 'Grit::Actor' then options[:actor]
when 'Hash' then Grit::Actor.new(actor[:name], actor[:email])
when 'String' then Grit::Actor.from_stirng(actor)
else begin
if actor.respond_to?(:name) and actor.respond_to?(:email)
Grit::Actor.new(actor.name, actor.email)
else
config = Grit::Config.new(repo)
Grit::Actor.new(config['user.name'], config['user.email'])
end
end
end
@last_actor
end
end

View File

@ -26,9 +26,6 @@ class Project < ActiveRecord::Base
validates :owner, :presence => true validates :owner, :presence => true
validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS }
validates_attachment_size :srpm, :less_than => 500.megabytes
validates_attachment_content_type :srpm, :content_type => ['application/octet-stream', "application/x-rpm", "application/x-redhat-package-manager"], :message => I18n.t('layout.invalid_content_type')
attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki
attr_readonly :name attr_readonly :name
@ -41,34 +38,50 @@ class Project < ActiveRecord::Base
scope :addable_to_repository, lambda { |repository_id| where("projects.id NOT IN (SELECT project_to_repositories.project_id FROM project_to_repositories WHERE (project_to_repositories.repository_id = #{ repository_id }))") } scope :addable_to_repository, lambda { |repository_id| where("projects.id NOT IN (SELECT project_to_repositories.project_id FROM project_to_repositories WHERE (project_to_repositories.repository_id = #{ repository_id }))") }
after_create :attach_to_personal_repository after_create :attach_to_personal_repository
after_create :create_git_repo
after_save :create_wiki
after_commit(:on => :create) {|p| p.fork_git_repo unless p.is_root?} # later with resque
after_destroy :destroy_git_repo has_ancestry :orphan_strategy => :rootify #:adopt not available yet
after_destroy :destroy_wiki
after_commit(:on => :create) {|p| p.import_attached_srpm if p.srpm?}# later with resque # should be after create_git_repo
# after_rollback lambda { destroy_git_repo rescue true if new_record? }
has_ancestry
has_attached_file :srpm
include Modules::Models::Owner include Modules::Models::Owner
include Modules::Models::Git
include Modules::Models::Wiki
class << self
def find_by_owner_and_name(owner_name, project_name)
owner = User.find_by_uname(owner_name) || Group.find_by_uname(owner_name) || User.by_uname(owner_name).first || Group.by_uname(owner_name).first and
scoped = where(:owner_id => owner.id, :owner_type => owner.class) and
scoped.find_by_name(project_name) || scoped.by_name(project_name).first
# owner.projects.find_by_name(project_name) || owner.projects.by_name(project_name).first # TODO force this work?
end
def find_by_owner_and_name!(owner_name, project_name)
find_by_owner_and_name(owner_name, project_name) or raise ActiveRecord::RecordNotFound
end
end
def to_param def to_param
name name
end end
def self.find_by_owner_and_name(owner_name, project_name) def members
owner = User.find_by_uname(owner_name) || Group.find_by_uname(owner_name) || User.by_uname(owner_name).first || Group.by_uname(owner_name).first and collaborators + groups.map(&:members).flatten
scoped = where(:owner_id => owner.id, :owner_type => owner.class) and
scoped.find_by_name(project_name) || scoped.by_name(project_name).first
# owner.projects.find_by_name(project_name) || owner.projects.by_name(project_name).first # TODO force this work?
end end
def self.find_by_owner_and_name!(owner_name, project_name) def platforms
find_by_owner_and_name(owner_name, project_name) or raise ActiveRecord::RecordNotFound @platforms ||= repositories.map(&:platform).uniq
end
def owner_and_admin_ids
recipients = self.relations.by_role('admin').where(:actor_type => 'User').map { |rel| rel.read_attribute(:actor_id) }
recipients = recipients | [self.owner_id] if self.owner_type == 'User'
recipients
end
def public?
visibility == 'open'
end
def owner?(user)
owner == user
end end
def build_for(platform, user, arch = 'i586', auto_publish = false, mass_build_id = nil, priority = 0) def build_for(platform, user, arch = 'i586', auto_publish = false, mass_build_id = nil, priority = 0)
@ -94,90 +107,6 @@ class Project < ActiveRecord::Base
end end
end end
def tags
self.git_repository.tags #.sort_by{|t| t.name.gsub(/[a-zA-Z.]+/, '').to_i}
end
def branches
self.git_repository.branches
end
def branches_and_tags
#@branches_and_tags ||= branches + tags # ???
branches + tags
end
def last_active_branch
@last_active_branch ||= branches.inject do |r, c|
r_last = r.commit.committed_date || r.commit.authored_date unless r.nil?
c_last = c.commit.committed_date || c.commit.authored_date
if r.nil? or r_last < c_last
r = c
end
r
end
@last_active_branch
end
def branch(name = nil)
name = default_branch if name.blank?
branches.select{|b| b.name == name}.first
end
def tree_info(tree, treeish = nil, path = nil)
treeish = tree.id unless treeish.present?
# initialize result as hash of <tree_entry> => nil
res = (tree.trees.sort + tree.blobs.sort).inject({}){|h, e| h.merge!({e => nil})}
# fills result vith commits that describes this file
res = res.inject(res) do |h, (entry, commit)|
# only if commit == nil ...
if commit.nil? and entry.respond_to? :name
# ... find last commit corresponds to this file ...
c = git_repository.log(treeish, File.join([path, entry.name].compact), :max_count => 1).first
# ... and add it to result.
h[entry] = c
# find another files, that linked to this commit and set them their commit
# c.diffs.map{|diff| diff.b_path.split(File::SEPARATOR, 2).first}.each do |name|
# h.each_pair do |k, v|
# h[k] = c if k.name == name and v.nil?
# end
# end
end
h
end
end
def versions
tags.map(&:name) + branches.map{|b| "latest_#{b.name}"}
end
def versions_for_group_select
[
['Branches', branches.map{|b| "latest_#{b.name}"}],
['Tags', tags.map(&:name)]
]
end
def members
collaborators + groups.map(&:members).flatten
end
def git_repository
@git_repository ||= Git::Repository.new(path)
end
def git_repo_name
File.join owner.uname, name
end
def wiki_repo_name
File.join owner.uname, "#{name}.wiki"
end
def public?
visibility == 'open'
end
def fork(new_owner) def fork(new_owner)
dup.tap do |c| dup.tap do |c|
c.parent_id = id c.parent_id = id
@ -187,12 +116,8 @@ class Project < ActiveRecord::Base
end end
end end
def path def human_average_build_time
build_path(git_repo_name) I18n.t("layout.projects.human_average_build_time", {:hours => (average_build_time/3600).to_i, :minutes => (average_build_time%3600/60).to_i})
end
def wiki_path
build_wiki_path(git_repo_name)
end end
def xml_rpc_create(repository) def xml_rpc_create(repository)
@ -213,101 +138,9 @@ class Project < ActiveRecord::Base
end end
end end
def platforms
@platforms ||= repositories.map(&:platform).uniq
end
def import_srpm(srpm_path = srpm.path, branch_name = 'import')
system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm_path} #{path} #{branch_name} >> /dev/null 2>&1")
end
def owner?(user)
owner == user
end
def owner_and_admin_ids
recipients = self.relations.by_role('admin').where(:actor_type => 'User').map { |rel| rel.read_attribute(:actor_id) }
recipients = recipients | [self.owner_id] if self.owner_type == 'User'
recipients
end
def human_average_build_time
time = average_build_time
I18n.t("layout.projects.human_average_build_time", {:hours => (time/3600).to_i, :minutes => (time%3600/60).to_i})
end
def full_name
@full_name ||= "#{owner.uname}/#{name}"
end
protected protected
def build_path(dir)
File.join(APP_CONFIG['root_path'], 'git_projects', "#{dir}.git")
end
def build_wiki_path(dir)
File.join(APP_CONFIG['root_path'], 'git_projects', "#{dir}.wiki.git")
end
def attach_to_personal_repository def attach_to_personal_repository
repositories << self.owner.personal_repository if !repositories.exists?(:id => self.owner.personal_repository) repositories << self.owner.personal_repository if !repositories.exists?(:id => self.owner.personal_repository)
end end
def create_git_repo
if is_root?
Grit::Repo.init_bare(path)
write_hook
end
end
def fork_git_repo
dummy = Grit::Repo.new(path) rescue parent.git_repository.repo.fork_bare(path)
write_hook
end
later :fork_git_repo, :queue => :fork_import
def destroy_git_repo
FileUtils.rm_rf path
end
def import_attached_srpm
if srpm?
import_srpm # srpm.path
self.srpm = nil; save # clear srpm
end
end
later :import_attached_srpm, :queue => :fork_import
def create_wiki
if has_wiki && !FileTest.exist?(wiki_path)
Grit::Repo.init_bare(wiki_path)
wiki = Gollum::Wiki.new(wiki_path, {:base_path => Rails.application.routes.url_helpers.project_wiki_index_path(owner, self)})
wiki.write_page('Home', :markdown, I18n.t("wiki.seed.welcome_content"),
{:name => owner.name, :email => owner.email, :message => 'Initial commit'})
end
end
def destroy_wiki
FileUtils.rm_rf wiki_path
end
def write_hook
is_production = Rails.env == "production"
hook = File.join(::Rails.root.to_s, 'tmp', "post-receive-hook")
FileUtils.cp(File.join(::Rails.root.to_s, 'bin', "post-receive-hook.partial"), hook)
File.open(hook, 'a') do |f|
s = "\n /bin/bash -l -c \"cd #{is_production ? '/srv/rosa_build/current' : Rails.root.to_s} && #{is_production ? 'RAILS_ENV=production' : ''} bundle exec rake hook:enqueue[$owner,$reponame,$newrev,$oldrev,$ref,$newrev_type,$oldrev_type]\""
s << " > /dev/null 2>&1" if is_production
s << "\ndone\n"
f.write(s)
f.chmod(0755)
end
hook_file = File.join(path, 'hooks', 'post-receive')
FileUtils.cp(hook, hook_file)
FileUtils.rm_rf(hook)
rescue Exception # FIXME
end
end end

View File

@ -9,7 +9,7 @@ class PullRequest < ActiveRecord::Base
validate :uniq_merge validate :uniq_merge
validates_each :head_ref, :base_ref do |record, attr, value| validates_each :head_ref, :base_ref do |record, attr, value|
project = attr == :head_ref ? record.head_project : record.base_project project = attr == :head_ref ? record.head_project : record.base_project
if !((project.branches + project.tags).map(&:name).include?(value) || project.git_repository.commits.map(&:id).include?(value)) if !((project.repo.branches_and_tags).map(&:name).include?(value) || project.git_repository.commits.map(&:id).include?(value))
record.errors.add attr, I18n.t('projects.pull_requests.wrong_ref') record.errors.add attr, I18n.t('projects.pull_requests.wrong_ref')
end end
end end
@ -194,13 +194,13 @@ class PullRequest < ActiveRecord::Base
def clean def clean
Dir.chdir(path) do Dir.chdir(path) do
base_project.branches.each {|branch| system 'git', 'checkout', branch.name} base_project.repo.branches.each {|branch| system 'git', 'checkout', branch.name}
system 'git', 'checkout', base_ref system 'git', 'checkout', base_ref
base_project.branches.each do |branch| base_project.repo.branches.each do |branch|
system 'git', 'branch', '-D', branch.name unless [base_ref, head_branch].include? branch.name system 'git', 'branch', '-D', branch.name unless [base_ref, head_branch].include? branch.name
end end
base_project.tags.each do |tag| base_project.repo.tags.each do |tag|
system 'git', 'tag', '-d', tag.name unless [base_ref, head_branch].include? tag.name system 'git', 'tag', '-d', tag.name unless [base_ref, head_branch].include? tag.name
end end
end end

View File

@ -0,0 +1,21 @@
.leftlist= f.label :body_ru, t("activerecord.attributes.flash_notify.body_ru"), :class => :label
.rightlist= f.text_area :body_ru, :class => 'text_field'
.both
.leftlist= f.label :body_en, t("activerecord.attributes.flash_notify.body_en"), :class => :label
.rightlist= f.text_area :body_en, :class => 'text_field'
.both
.leftlist= f.label :status, t("activerecord.attributes.flash_notify.status"), :class => :label
.rightlist= f.select :status, FlashNotify::STATUSES
.both
.leftlist= f.label :published, t("activerecord.attributes.flash_notify.published"), :class => :label
.rightlist= f.check_box :published
.both
.button_block
= submit_tag t("layout.save")
%span.text_button_padding= t("layout.or")
= link_to t("layout.cancel"), admin_flash_notifies_path, :class => "button"

View File

@ -0,0 +1,6 @@
%h3= t("layout.flash_notifies.edit_header")
= form_for @flash_notify, :url => admin_flash_notify_path(@flash_notify), :html => { :class => :form } do |f|
= render "form", :f => f
= render 'submenu'

View File

@ -0,0 +1,22 @@
= link_to t("layout.flash_notifies.new"), new_admin_flash_notify_path, :class => 'button' if can? :create, FlashNotify
%table#myTable.tablesorter.flash_notifys{:cellspacing => "0", :cellpadding => "0"}
%thead
%tr
%th.th1= t("activerecord.attributes.flash_notify.body_en")
%th.th2= t("activerecord.attributes.flash_notify.body_ru")
%th.th3= t("activerecord.attributes.flash_notify.published")
%th.th3= t("layout.flash_notifies.actions")
%tbody
- @flash_notifies.each do |flash_notify|
%tr{:class => cycle("odd", "even")}
%td= flash_notify.body_en.truncate 18
%td= flash_notify.body_ru.truncate 18
%td= flash_notify.published
%td
= link_to t("layout.flash_notifies.edit"), edit_admin_flash_notify_path(flash_notify)
= link_to t("layout.flash_notifies.delete"), admin_flash_notify_path(flash_notify), :method => :delete, :confirm => t("layout.mass_builds.cancel_confirm") if can?(:delete, flash_notify)
= will_paginate @flash_notifies
= render 'submenu'

View File

@ -0,0 +1,6 @@
%h3= t("layout.flash_notifies.new_header")
= form_for @flash_notify, :url => admin_flash_notifies_path, :html => { :class => :form } do |f|
= render "form", :f => f
= render 'submenu'

View File

@ -0,0 +1,10 @@
- if current_user || APP_CONFIG['anonymous_access']
.flash_notify
- if (flash_notify = FlashNotify.published.first) && flash_notify.should_show?(cookies[:flash_notify_hash])
.alert{:class => "alert-#{flash_notify.status}"}
= flash_notify.body I18n.locale
%a.close#close-alert{:'data-dismiss'=>"alert", :href=>"#"} &times;
:javascript
var FLASH_HASH_ID = "#{flash_notify.hash_id}";
var FLASH_EXPIRES_AT = "#{Date.today + 1.year}";

View File

@ -47,6 +47,7 @@
= yield :feed_tabs = yield :feed_tabs
.both .both
= render "layouts/flashes" = render "layouts/flashes"
= render "layouts/notifies"
%article %article
- if content_for?(:sidebar) - if content_for?(:sidebar)
%aside= yield :sidebar %aside= yield :sidebar

View File

@ -6,8 +6,8 @@
=image_tag 'zip.png', :alt => 'ZIP' =image_tag 'zip.png', :alt => 'ZIP'
%b.caret %b.caret
%ul.dropdown-menu %ul.dropdown-menu
%li=link_to "tar.gz", archive_path(project, 'tar', @treeish) %li=link_to "tar.gz", archive_path(project, @treeish, 'tar')
%li=link_to "zip", archive_path(project, 'zip', @treeish) %li=link_to "zip", archive_path(project, @treeish, 'zip')
= text_field_tag :url, git_repo_url(project.git_repo_name), :class => 'name', :spellcheck => 'false', :readonly => true = text_field_tag :url, git_repo_url(project.git_repo_name), :class => 'name', :spellcheck => 'false', :readonly => true
.git_help ? .git_help ?

View File

@ -1,12 +1,12 @@
- content_for :submenu do - content_for :submenu do
- act = action_name.to_sym; contr = controller_name.to_sym - act = action_name.to_sym; contr = controller_name.to_sym; treeish = params[:treeish].presence || @project.default_branch
.left .left
.table-sort-left=image_tag visibility_icon(@project.visibility) .table-sort-left=image_tag visibility_icon(@project.visibility)
.table-sort-right=@project.name .table-sort-right=@project.name
%nav %nav
%ul %ul
%li= link_to t("project_menu.project"), project_path(@project), :class => (act.in?([:show, :edit]) && contr.in?([:trees, :blobs]) ? 'active' : nil) %li= link_to t("project_menu.project"), tree_path(@project, treeish), :class => (act.in?([:show, :edit]) && contr.in?([:trees, :blobs]) ? 'active' : nil)
%li= link_to t("project_menu.commits"), commits_path(@project), :class => (act.in?([:index, :show]) && contr == :commits ? 'active' : nil) %li= link_to t("project_menu.commits"), commits_path(@project, treeish), :class => (act.in?([:index, :show]) && contr == :commits ? 'active' : nil)
- if @project.is_package and can?(:read, @project => BuildList) - if @project.is_package and can?(:read, @project => BuildList)
%li= link_to t("project_menu.builds"), project_build_lists_path(@project), :class => (contr == :build_lists ? 'active' : nil) %li= link_to t("project_menu.builds"), project_build_lists_path(@project), :class => (contr == :build_lists ? 'active' : nil)
- if @project.has_issues - if @project.has_issues

View File

@ -13,10 +13,7 @@
%h3= t("activerecord.attributes.build_list.save_to_platform") %h3= t("activerecord.attributes.build_list.save_to_platform")
.lineForm= f.select :save_to_platform_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]} .lineForm= f.select :save_to_platform_id, @project.repositories.collect{|r| ["#{r.platform.name}/#{r.name}", r.platform.id]}
%h3= t("activerecord.attributes.build_list.project_version") %h3= t("activerecord.attributes.build_list.project_version")
- if controller.action_name == 'new' .lineForm= f.select :project_version, versions_for_group_select(@project), :selected => params[:build_list].try(:fetch, :project_version) || "latest_" + @project.default_branch
.lineForm= f.select :project_version, @project.versions_for_group_select, :selected => "latest_" + @project.default_branch
- else
.lineForm= f.select :project_version, @project.versions_for_group_select
%h3= t("activerecord.attributes.build_list.arch") %h3= t("activerecord.attributes.build_list.arch")
- Arch.recent.each do |arch| - Arch.recent.each do |arch|
.both .both

View File

@ -35,7 +35,7 @@
.both .both
.leftlist= t("activerecord.attributes.build_list.update_type") .leftlist= t("activerecord.attributes.build_list.update_type")
.rightlist .rightlist
- if @build_list.can_publish? and can?(:publish, @build_list) - if @build_list.can_publish? && can?(:publish, @build_list)
= f.select :update_type, options_for_select(build_list_classified_update_types, @build_list.update_type) = f.select :update_type, options_for_select(build_list_classified_update_types, @build_list.update_type)
- else - else
= @build_list.update_type = @build_list.update_type
@ -81,11 +81,11 @@
= "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}" = "#{@build_list.human_current_duration} / #{@build_list.project.human_average_build_time}"
.both .both
- if @build_list.can_cancel? and can?(:cancel, @build_list) - if @build_list.can_cancel? && can?(:cancel, @build_list)
= link_to t("layout.build_lists.cancel"), cancel_build_list_path(@build_list), = link_to t("layout.build_lists.cancel"), cancel_build_list_path(@build_list),
:method => :put, :confirm => t("layout.confirm"), :class => 'button' :method => :put, :confirm => t("layout.confirm"), :class => 'button'
- if @build_list.can_publish? and @build_list.save_to_platform.released and @build_list.advisory.nil? - if @build_list.can_publish? && @build_list.save_to_platform.released && @build_list.advisory.nil? && can?(:publish, @build_list)
#advisory_block #advisory_block
.leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory") .leftlist= label_tag :attach_advisory, t("layout.build_lists.attached_advisory")
.rightlist .rightlist
@ -123,8 +123,8 @@
var r = new Rosa.Routers.BuildListsAdvisoriesRouter(); var r = new Rosa.Routers.BuildListsAdvisoriesRouter();
}); });
= submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if @build_list.can_publish? and can?(:publish, @build_list) = submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish' if @build_list.can_publish? && can?(:publish, @build_list)
= submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if @build_list.can_reject_publish? and can?(:reject_publish, @build_list) = submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish' if @build_list.can_reject_publish? && can?(:reject_publish, @build_list)
.hr .hr
%h3= t("layout.build_lists.items_header") %h3= t("layout.build_lists.items_header")

View File

@ -4,7 +4,7 @@
= render 'fork' = render 'fork'
.both .both
= form_tag blob_path(@project, @treeish, @path), :name => 'blob-editor', :method => :put do = form_tag edit_blob_path(@project, @treeish, @path), :name => 'blob-editor', :method => :put do
.file= text_area_tag :content, @blob.data, :id => 'code' .file= text_area_tag :content, @blob.data, :id => 'code'
.both .both

View File

@ -0,0 +1,8 @@
%table.table.blob
%tr
%td.lines
%td.blob
:plain
<br/>
<pre>#{link_to @blob.basename, raw_path(@project, @treeish, @path)}</pre>
<br/>

View File

@ -0,0 +1,8 @@
%table.table.blob
%tr
%td.lines
%td.blob
:plain
<br/>
<center><img src='#{raw_path(@project, @treeish, @path)}'/></center>
<br/>

View File

@ -0,0 +1,6 @@
.gutter= render_line_numbers(@blob.loc)
#output.formatted.cm-s-default
%pre#code
:preserve
#{h(@blob.data).html_safe}
.both

View File

@ -4,37 +4,10 @@
= render 'fork' = render 'fork'
.both .both
- render_way = choose_render_way(@blob)
.file .file
.top= render 'top', :render_way => render_way .top= render 'top'
.data .data= render "render_as_#{@blob.render_as}"
- case render_way
- when :image
%table.table.blob
%tr
%td.lines
%td.blob
:plain
<br/>
<center> <img src='?raw=true'/></center>
<br/>
- when :text
.gutter= render_line_numbers(@text.length)
#output.formatted.cm-s-default
%pre#code
=#{render_blob(@blob)}
:preserve
#{h(@blob.data).html_safe}
.both
- when :binary
%table.table.blob
%tr
%td.lines
%td.blob
:plain
<br/>
<pre>#{ link_to @blob.basename, raw_path(@project, @treeish, @path) }</pre>
<br/>
:javascript :javascript
$(document).ready(function() { $(document).ready(function() {
var text = $('#code').text().replace(/&amp;/gi, '&'); var text = $('#code').text().replace(/&amp;/gi, '&');

View File

@ -1,20 +1,20 @@
.l .l
= @blob.mode = @blob.mode
\| \|
- if render_way == :text - if @blob.render_as == :text
#{@text.length} lines (#{@text.select{|s| s.strip.length > 0}.length} sloc) #{@blob.loc} lines (#{@blob.sloc} sloc)
\| \|
= number_to_human_size @blob.size = number_to_human_size @blob.size
.r .r
- if render_way == :text and can? :write, @project and @treeish.in? @project.branches.map(&:name) - if @blob.render_as == :text && can?(:write, @project) && @branch.present?
= link_to "Edit", edit_blob_path(@project, @treeish, @path) = link_to "Edit", edit_blob_path(@project, @treeish, @path)
\| \|
- if render_way == :text and params[:action] != 'show' - if @blob.render_as == :text && params[:action] != 'show'
= link_to "Normal", blob_path(@project, @treeish, @path) = link_to "Normal", blob_path(@project, @treeish, @path)
\| \|
= link_to "Raw", raw_path(@project, @treeish, @path) = link_to "Raw", raw_path(@project, @treeish, @path)
\| \|
- if render_way == :text and params[:action] != 'blame' - if @blob.render_as == :text && params[:action] != 'blame'
= link_to "Blame", blame_path(@project, @treeish, @path) = link_to "Blame", blame_path(@project, @treeish, @path)
\| \|
= link_to "History", commits_path(@project, @treeish, @path) = link_to "History", commits_path(@project, @treeish, @path)

View File

@ -20,7 +20,6 @@
.l= render 'whereami' .l= render 'whereami'
.both .both
- render_way = choose_render_way(@blob)
.file .file
.top= render 'top', :render_way => render_way .top= render 'top'
.blame_data= render 'blame_table' if @blame.first.first.present? .blame_data= render 'blame_table' if @blame.first.first.present?

View File

@ -7,4 +7,4 @@
.r= link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@project, commit_id, commit_diff.b_path) .r= link_to "view file @ #{short_hash_id(commit_id)}", blob_path(@project, commit_id, commit_diff.b_path)
.clear .clear
.diff_data= render_diff(commit_diff, commit_diff_counter) unless (@git_repository.tree(commit_id) / commit_diff.b_path).binary? .diff_data= render_diff(commit_diff, commit_diff_counter) unless (@project.repo.tree(commit_id) / commit_diff.b_path).binary?

View File

@ -13,7 +13,6 @@
-begin -begin
= render_commit_stats(stats) = render_commit_stats(stats)
= render :partial => 'commit_diff', :collection => @commit.diffs = render :partial => 'commit_diff', :collection => @commit.diffs
- rescue Grit::Git::GitTimeout - rescue Grit::Git::GitTimeout
%p= t 'layout.git.repositories.commit_diff_too_big' %p= t 'layout.git.repositories.commit_diff_too_big'

View File

@ -3,4 +3,4 @@
= render 'repo_block', :project => @project = render 'repo_block', :project => @project
= render :partial => 'commits', :object => @commits = render :partial => 'commits', :object => @commits
= render 'paginate' if @render_paginate = render 'paginate' if @path.blank?

View File

@ -31,7 +31,7 @@
.pic= image_tag 'folder.png' .pic= image_tag 'folder.png'
.name= link_to(entry.name, tree_path(@project, @treeish, entry_path), :class => 'files-see') .name= link_to(entry.name, tree_path(@project, @treeish, entry_path), :class => 'files-see')
%td %td
%span{:style => "display: none;"}= commit.committed_date || commit.authored_date %span{:style => "display: none;"}= date = commit.committed_date || commit.authored_date
= l(commit.committed_date || commit.authored_date, :format => :short) = l(date, :format => :short)
%td= commit.short_message %td= commit.short_message
%td= (commit.committer || commit.author).name %td= (commit.committer || commit.author).name

View File

@ -35,7 +35,7 @@
.both .both
- if [:edit, :update].include? act - if [:edit, :update].include? act
.leftlist= t("activerecord.attributes.project.default_branch") .leftlist= t("activerecord.attributes.project.default_branch")
.rightlist= f.select :default_branch, options_from_collection_for_select(@project.branches, :name, :name, @project.default_branch), :class => 'sel80', :id => 'branch_selector' .rightlist= f.select :default_branch, options_from_collection_for_select(@project.repo.branches, :name, :name, @project.default_branch), :class => 'sel80', :id => 'branch_selector'
.both .both
- if [:edit, :update].include? act - if [:edit, :update].include? act
.leftlist .leftlist

View File

@ -51,10 +51,10 @@
:javascript :javascript
$(function() { $(function() {
$('input#base_refs').autocomplete({ $('input#base_refs').autocomplete({
source: #{@pull.base_project.branches_and_tags.map &:name} source: #{@pull.base_project.repo.branches_and_tags.map &:name}
}); });
$('input#head_refs').autocomplete({ $('input#head_refs').autocomplete({
source: #{@project.branches_and_tags.map &:name} source: #{@project.repo.branches_and_tags.map &:name}
}); });
}); });

View File

@ -43,5 +43,5 @@
.both .both
.leftlist .leftlist
\  \ 
.rightlist= submit_tag t("layout.save") .rightlist= submit_tag t("layout.save"), :data => {:"disable-with" => t("layout.saving")}
.both .both

View File

@ -26,6 +26,7 @@ en:
delete: Erase delete: Erase
delete_selected: Remove selected delete_selected: Remove selected
save: Save save: Save
saving: Saving
clone: Clone clone: Clone
search_by_name: Filter by name search_by_name: Filter by name
are_you_sure: "Sure?" are_you_sure: "Sure?"

View File

@ -38,5 +38,6 @@ en:
admins_menu: admins_menu:
users: Users users: Users
register_requests: Invites register_requests: Invites
flash_notifies: Notifies
event_logs: Event log event_logs: Event log
resque_server: Resque resque_server: Resque

View File

@ -38,5 +38,6 @@ ru:
admins_menu: admins_menu:
users: Пользователи users: Пользователи
register_requests: Инвайты register_requests: Инвайты
flash_notifies: Оповещения
event_logs: Лог событий event_logs: Лог событий
resque_server: Resque resque_server: Resque

View File

@ -0,0 +1,28 @@
en:
layout:
flash_notifies:
list_header: Notifies
new: New notify
new_header: New notify
actions: Actions
edit: Edit
edit_header: Edit notify
delete: Delete
flash:
flash_notify:
saved: Notify added
save_error: Unable to add notify
destroyed: Notify deleted
activerecord:
models:
flash_notify: Notify
attributes:
flash_notify:
body_ru: Body Ru
body_en: Body En
published: Published
status: Status
created_at: Created
updated_at: Updated

View File

@ -0,0 +1,28 @@
ru:
layout:
flash_notifies:
list_header: Оповещения
new: Новое оповещение
new_header: Новое оповещение
actions: Действия
edit: Редактирование
edit_header: Редактировать оповещение
delete: Удалить
flash:
flash_notify:
saved: Оповещение сохранено
save_error: Не получилось сохранить оповещение
destroyed: Оповещение удалено
activerecord:
models:
flash_notify: Оповещение
attributes:
flash_notify:
body_ru: Текст Ru
body_en: Текст En
published: Опубликовано
status: Статус
created_at: Создано
updated_at: Обновлено

View File

@ -26,6 +26,7 @@ ru:
delete: Удалить delete: Удалить
delete_selected: Удалить выбранное delete_selected: Удалить выбранное
save: Сохранить save: Сохранить
saving: Сохранение...
clone: Клонировать clone: Клонировать
search_by_name: Фильтр по имени search_by_name: Фильтр по имени
are_you_sure: "Вы уверены?" are_you_sure: "Вы уверены?"

View File

@ -32,8 +32,9 @@ Rosa::Application.routes.draw do
get :reject get :reject
end end
end end
resources :flash_notifies
resources :event_logs, :only => :index resources :event_logs, :only => :index
constraints AdminAccess do constraints Rosa::Constraints::AdminAccess do
mount Resque::Server => 'resque' mount Resque::Server => 'resque'
end end
end end
@ -133,7 +134,6 @@ Rosa::Application.routes.draw do
end end
resources :projects, :only => [:index, :new, :create] resources :projects, :only => [:index, :new, :create]
scope ':owner_name/:project_name', :constraints => {:project_name => Project::NAME_REGEXP} do # project scope ':owner_name/:project_name', :constraints => {:project_name => Project::NAME_REGEXP} do # project
scope :as => 'project' do scope :as => 'project' do
resources :wiki do resources :wiki do
@ -188,7 +188,7 @@ Rosa::Application.routes.draw do
end end
# Resource # Resource
get '/edit' => 'projects#edit', :as => :edit_project get '/modify' => 'projects#edit', :as => :edit_project
put '/' => 'projects#update' put '/' => 'projects#update'
delete '/' => 'projects#destroy' delete '/' => 'projects#destroy'
# Member # Member
@ -196,41 +196,43 @@ Rosa::Application.routes.draw do
get '/sections' => 'projects#sections', :as => :sections_project get '/sections' => 'projects#sections', :as => :sections_project
post '/sections' => 'projects#sections' post '/sections' => 'projects#sections'
delete '/remove_user' => 'projects#remove_user', :as => :remove_user_project delete '/remove_user' => 'projects#remove_user', :as => :remove_user_project
constraints :treeish => /[^\/]+/ do constraints :treeish => /.+/ do
# Tree constraints Rosa::Constraints::Treeish do
get '/' => "git/trees#show", :as => :project # Tree
get '/tree/:treeish(/*path)' => "git/trees#show", :defaults => {:treeish => :master}, :as => :tree, :format => false get '/' => "git/trees#show", :as => :project
# Commits get '/tree/:treeish(/*path)' => "git/trees#show", :as => :tree, :format => false
get '/commits/:treeish(/*path)' => "git/commits#index", :defaults => {:treeish => :master}, :as => :commits, :format => false # Commits
get '/commit/:id(.:format)' => "git/commits#show", :as => :commit get '/commits/:treeish(/*path)' => "git/commits#index", :as => :commits, :format => false
# Commit comments get '/commit/:id(.:format)' => "git/commits#show", :as => :commit
post '/commit/:commit_id/comments(.:format)' => "comments#create", :as => :project_commit_comments # Commit comments
get '/commit/:commit_id/comments/:id(.:format)' => "comments#edit", :as => :edit_project_commit_comment post '/commit/:commit_id/comments(.:format)' => "comments#create", :as => :project_commit_comments
put '/commit/:commit_id/comments/:id(.:format)' => "comments#update", :as => :project_commit_comment get '/commit/:commit_id/comments/:id(.:format)' => "comments#edit", :as => :edit_project_commit_comment
delete '/commit/:commit_id/comments/:id(.:format)' => "comments#destroy" put '/commit/:commit_id/comments/:id(.:format)' => "comments#update", :as => :project_commit_comment
# Commit subscribes delete '/commit/:commit_id/comments/:id(.:format)' => "comments#destroy"
post '/commit/:commit_id/subscribe' => "commit_subscribes#create", :as => :subscribe_commit # Commit subscribes
delete '/commit/:commit_id/unsubscribe' => "commit_subscribes#destroy", :as => :unsubscribe_commit post '/commit/:commit_id/subscribe' => "commit_subscribes#create", :as => :subscribe_commit
# Editing files delete '/commit/:commit_id/unsubscribe' => "commit_subscribes#destroy", :as => :unsubscribe_commit
get '/blob/:treeish/*path/edit' => "git/blobs#edit", :defaults => {:treeish => :master}, :as => :edit_blob # Editing files
put '/blob/:treeish/*path' => "git/blobs#update", :defaults => {:treeish => :master}, :format => false get '/edit/:treeish/*path' => "git/blobs#edit", :as => :edit_blob, :format => false
# Blobs put '/edit/:treeish/*path' => "git/blobs#update", :format => false
get '/blob/:treeish/*path' => "git/blobs#show", :defaults => {:treeish => :master}, :as => :blob, :format => false # Blobs
# Blame get '/blob/:treeish/*path' => "git/blobs#show", :as => :blob, :format => false
get '/blame/:treeish/*path' => "git/blobs#blame", :defaults => {:treeish => :master}, :as => :blame, :format => false # Blame
# Raw get '/blame/:treeish/*path' => "git/blobs#blame", :as => :blame, :format => false
get '/raw/:treeish/*path' => "git/blobs#raw", :defaults => {:treeish => :master}, :as => :raw, :format => false # Raw
# Archive get '/raw/:treeish/*path' => "git/blobs#raw", :as => :raw, :format => false
get '/archive/:format/tree/:treeish' => "git/trees#archive", :defaults => {:treeish => :master}, :as => :archive, :format => /zip|tar/ # Archive
get '/archive/:treeish.:format' => "git/trees#archive", :as => :archive, :format => /zip|tar/
end
end end
end end
end end
scope ':uname' do # project owner profile scope ':uname' do # project owner profile
constraints OwnerConstraint.new(User) do constraints Rosa::Constraints::Owner.new(User) do
get '/' => 'users/profile#show', :as => :user get '/' => 'users/profile#show', :as => :user
end end
constraints OwnerConstraint.new(Group, true) do constraints Rosa::Constraints::Owner.new(Group, true) do
get '/' => 'groups/profile#show', :as => :group get '/' => 'groups/profile#show', :as => :group
end end
end end

View File

@ -0,0 +1,11 @@
class CreateFlashNotifies < ActiveRecord::Migration
def change
create_table :flash_notifies do |t|
t.text :body_ru, :null => false
t.text :body_en, :null => false
t.string :status, :null => false
t.boolean :published, :null => false, :default => true
t.timestamps
end
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120703101719) do ActiveRecord::Schema.define(:version => 20120719045806) do
create_table "activity_feeds", :force => true do |t| create_table "activity_feeds", :force => true do |t|
t.integer "user_id", :null => false t.integer "user_id", :null => false
@ -159,6 +159,15 @@ ActiveRecord::Schema.define(:version => 20120703101719) do
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end end
create_table "flash_notifies", :force => true do |t|
t.text "body_ru", :null => false
t.text "body_en", :null => false
t.string "status", :null => false
t.boolean "published", :default => true, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "groups", :force => true do |t| create_table "groups", :force => true do |t|
t.integer "owner_id" t.integer "owner_id"
t.datetime "created_at", :null => false t.datetime "created_at", :null => false

View File

@ -21,4 +21,8 @@ Add to /etc/rc.d/rc.sysinit
sudo urpmi lib64icu-devel # mandriva sudo urpmi lib64icu-devel # mandriva
gem install charlock_holmes -- --with-icu-dir=/opt/local # macports gem install charlock_holmes -- --with-icu-dir=/opt/local # macports
sudo urpmi lib64magic-devel # mandriva
brew install libmagic; brew link libmagic # brew
gem install ruby-filemagic
git config --global core.quotepath false git config --global core.quotepath false

View File

@ -1,30 +1,26 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'charlock_holmes/string' require 'charlock_holmes/string'
# require 'iconv'
class String class String
def default_encoding! def default_encoding!
if ascii_only? default_encoding = Encoding.default_internal || Encoding::UTF_8
force_encoding(Encoding.default_internal || Encoding::UTF_8) if ascii_only? # no need to encode if ascii
else force_encoding(default_encoding)
force_encoding((detected = detect_encoding and detected[:encoding]) || Encoding.default_internal || Encoding::UTF_8).encode! else # should encode
options = {:invalid => :replace, :undef => :replace, :replace => ''}
if (detected = detect_encoding) && detected[:encoding]
force_encoding(detected[:encoding]).encode!(default_encoding, detected[:encoding], options)
end
# re-encode through UTF-16 to filter incorrect symbols
encode!(Encoding::UTF_16, default_encoding, options).encode!(default_encoding, Encoding::UTF_16)
raise unless valid_encoding? # check result
end end
rescue
replace "--broken encoding: #{detect_encoding[:encoding] || 'unknown'}"
ensure
self
end end
# def enforce_utf8(from = nil)
# begin
# is_utf8? ? self : ::Iconv.iconv('utf8', from, self).first
# rescue
# converter = ::Iconv.new('UTF-8//IGNORE//TRANSLIT', 'ASCII//IGNORE//TRANSLIT')
# # If Ruby 1.9, else another RubyEngine (ree, Ruby 1.8)
# begin
# converter.iconv(self).unpack('U*').select{|cp| cp < 127}.pack('U*').force_encoding('utf-8')
# rescue
# converter.iconv(self).unpack('U*').select{|cp| cp < 127}.pack('U*')
# end
# end
# end
# same as reverse.truncate.reverse # same as reverse.truncate.reverse
def rtruncate(length, options = {}) def rtruncate(length, options = {})
text = self.dup text = self.dup

View File

@ -1,11 +1,49 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
module Grit module Grit
class Blob class Blob
include Linguist::BlobHelper
MAX_VIEW_SIZE = 2.megabytes
MAX_DATA_SIZE = 50.megabytes
def data_with_limit
size <= MAX_DATA_SIZE ? data_without_limit : nil # 'Error: blob is too big'
end
alias_method_chain :data, :limit
def large?
size.to_i > MAX_VIEW_SIZE
end
def render_as
@render_as ||= case
when large?; :binary
when image?; :image
when text?; :text
else
:binary
end
end
# def file_mime_type
# @file_mime_type ||= data.file_type(:mime_type)
# end
#
# def text?
# file_mime_type =~ /^text\// # not binary?
# end
#
# def binary?
# not text? # file_mime_type !~ /^text\//
# # s = data.split(//); ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30 # works only for latin chars
# end
#
# def image?
# mime_type.match(/image/)
# end
DEFAULT_RAW_MIME_TYPE = MIME::Types[DEFAULT_MIME_TYPE].first DEFAULT_RAW_MIME_TYPE = MIME::Types[DEFAULT_MIME_TYPE].first
delegate :binary?, :ascii?, :encoding, :to => :raw_mime_type
def mime_type_with_class_store def mime_type_with_class_store
set_associated_mimes set_associated_mimes
@associated_mimes.first.simplified @associated_mimes.first.simplified
@ -25,29 +63,35 @@ module Grit
protected protected
# store all associated MIME::Types inside class # store all associated MIME::Types inside class
def set_associated_mimes def set_associated_mimes
@associated_mimes ||= [] @associated_mimes ||= []
if @associated_mimes.empty? if @associated_mimes.empty?
guesses = MIME::Types.type_for(self.name) rescue [DEFAULT_RAW_MIME_TYPE] guesses = MIME::Types.type_for(self.name) rescue [DEFAULT_RAW_MIME_TYPE]
guesses = [DEFAULT_RAW_MIME_TYPE] if guesses.empty? guesses = [DEFAULT_RAW_MIME_TYPE] if guesses.empty?
@associated_mimes = guesses.sort{|a,b| mime_sort(a, b)} @associated_mimes = guesses.sort{|a,b| mime_sort(a, b)}
end
@associated_mimes
end end
@associated_mimes
end
# TODO make more clever function # TODO make more clever function
def mime_sort(a,b) def mime_sort(a,b)
return 0 if a.media_type == b.media_type and a.registered? == b.registered? return 0 if a.media_type == b.media_type and a.registered? == b.registered?
return -1 if a.media_type == 'text' and !a.registered? return -1 if a.media_type == 'text' and !a.registered?
return 1 return 1
end end
end
class Repo
def branches_and_tags
branches + tags # @branches_and_tags ||= # ???
end
end end
end end
Grit::Git.git_timeout = 60 Grit::Git.git_timeout = 60
# Grit::Git.git_max_size = 5.megabytes
# Grit.debug = true # Grit.debug = true
GAP_REPO_PATH = '/tmp/gap_repo.git' GAP_REPO_PATH = '/tmp/gap_repo.git'
unless File.directory? GAP_REPO_PATH unless File.directory? GAP_REPO_PATH

View File

@ -1,18 +0,0 @@
# -*- encoding : utf-8 -*-
class OwnerConstraint
def initialize(class_name, bang = false)
@class_name = class_name
@finder = 'find_by_insensitive_uname'
@finder << '!' if bang
end
def matches?(request)
@class_name.send(@finder, request.params[:uname]).present?
end
end
class AdminAccess
def self.matches?(request)
!!request.env['warden'].user.try(:admin?)
end
end

View File

@ -0,0 +1,40 @@
# -*- encoding : utf-8 -*-
module Rosa
module Constraints
class Owner
def initialize(class_name, bang = false)
@class_name = class_name
@finder = 'find_by_insensitive_uname'
@finder << '!' if bang
end
def matches?(request)
@class_name.send(@finder, request.params[:uname]).present?
end
end
class AdminAccess
def self.matches?(request)
!!request.env['warden'].user.try(:admin?)
end
end
class Treeish
def self.matches?(request)
params = request.path_parameters
if params[:treeish] # parse existing branch (tag) and path
branch_or_tag = begin
(p = Project.find_by_owner_and_name params[:owner_name], params[:project_name]) &&
p.repo.branches_and_tags.detect{|t| params[:treeish].start_with?(t.name)}.try(:name) ||
params[:treeish].split('/').first
end
if path = params[:treeish].sub(branch_or_tag, '')[1..-1] and path.present?
params[:path] = File.join([path, params[:path]].compact)
end
params[:treeish] = branch_or_tag
end
true
end
end
end
end

171
lib/modules/models/git.rb Normal file
View File

@ -0,0 +1,171 @@
# -*- encoding : utf-8 -*-
module Modules
module Models
module Git
extend ActiveSupport::Concern
included do
validates_attachment_size :srpm, :less_than => 500.megabytes
validates_attachment_content_type :srpm, :content_type => ['application/octet-stream', "application/x-rpm", "application/x-redhat-package-manager"], :message => I18n.t('layout.invalid_content_type')
has_attached_file :srpm
# attr_accessible :srpm
after_create :create_git_repo
after_commit(:on => :create) {|p| p.fork_git_repo unless p.is_root?} # later with resque
after_commit(:on => :create) {|p| p.import_attached_srpm if p.srpm?} # later with resque # should be after create_git_repo
after_destroy :destroy_git_repo
# after_rollback lambda { destroy_git_repo rescue true if new_record? }
later :import_attached_srpm, :queue => :fork_import
later :fork_git_repo, :queue => :fork_import
end
def repo
@repo ||= Grit::Repo.new(path) rescue Grit::Repo.new(GAP_REPO_PATH)
end
def path
build_path(git_repo_name)
end
def git_repo_name
File.join owner.uname, name
end
def versions
repo.tags.map(&:name) + repo.branches.map{|b| "latest_#{b.name}"}
end
def update_file(path, data, options = {})
head = options[:head].to_s || default_branch
actor = get_actor(options[:actor])
filename = File.split(path).last
message = options[:message]
message = "Updated file #{filename}" if message.nil? or message.empty?
# can not write to unexisted branch
return false if repo.branches.select{|b| b.name == head}.size != 1
parent = repo.commits(head).first
index = repo.index
index.read_tree(parent.tree.id)
# can not create new file
return false if (index.current_tree / path).nil?
index.add(path, data)
index.commit(message, :parents => [parent], :actor => actor, :last_tree => parent.tree.id, :head => head)
end
def paginate_commits(treeish, options = {})
options[:page] = options[:page].try(:to_i) || 1
options[:per_page] = options[:per_page].try(:to_i) || 20
skip = options[:per_page] * (options[:page] - 1)
last_page = (skip + options[:per_page]) >= repo.commit_count(treeish)
[repo.commits(treeish, options[:per_page], skip), options[:page], last_page]
end
def tree_info(tree, treeish = nil, path = nil)
treeish ||= tree.id
# initialize result as hash of <tree_entry> => nil
res = (tree.trees.sort + tree.blobs.sort).inject({}){|h, e| h.merge!({e => nil})}
# fills result vith commits that describes this file
res = res.inject(res) do |h, (entry, commit)|
if commit.nil? and entry.respond_to?(:name) # only if commit == nil
# ... find last commit corresponds to this file ...
c = repo.log(treeish, File.join([path, entry.name].compact), :max_count => 1).first
# ... and add it to result.
h[entry] = c
# find another files, that linked to this commit and set them their commit
# c.diffs.map{|diff| diff.b_path.split(File::SEPARATOR, 2).first}.each do |name|
# h.each_pair do |k, v|
# h[k] = c if k.name == name and v.nil?
# end
# end
end
h
end
end
def import_srpm(srpm_path = srpm.path, branch_name = 'import')
system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm_path} #{path} #{branch_name} >> /dev/null 2>&1")
end
protected
def build_path(dir)
File.join(APP_CONFIG['root_path'], 'git_projects', "#{dir}.git")
end
def import_attached_srpm
if srpm?
import_srpm # srpm.path
self.srpm = nil; save # clear srpm
end
end
def create_git_repo
if is_root?
Grit::Repo.init_bare(path)
write_hook
end
end
def fork_git_repo
dummy = Grit::Repo.new(path) rescue parent.repo.fork_bare(path)
write_hook
end
def destroy_git_repo
FileUtils.rm_rf path
end
def write_hook
is_production = Rails.env == "production"
hook = File.join(::Rails.root.to_s, 'tmp', "post-receive-hook")
FileUtils.cp(File.join(::Rails.root.to_s, 'bin', "post-receive-hook.partial"), hook)
File.open(hook, 'a') do |f|
s = "\n /bin/bash -l -c \"cd #{is_production ? '/srv/rosa_build/current' : Rails.root.to_s} && #{is_production ? 'RAILS_ENV=production' : ''} bundle exec rake hook:enqueue[$owner,$reponame,$newrev,$oldrev,$ref,$newrev_type,$oldrev_type]\""
s << " > /dev/null 2>&1" if is_production
s << "\ndone\n"
f.write(s)
f.chmod(0755)
end
hook_file = File.join(path, 'hooks', 'post-receive')
FileUtils.cp(hook, hook_file)
FileUtils.rm_rf(hook)
rescue Exception # FIXME
end
def get_actor(actor = nil)
@last_actor = case actor.class.to_s
when 'Grit::Actor' then options[:actor]
when 'Hash' then Grit::Actor.new(actor[:name], actor[:email])
when 'String' then Grit::Actor.from_stirng(actor)
else begin
if actor.respond_to?(:name) and actor.respond_to?(:email)
Grit::Actor.new(actor.name, actor.email)
else
config = Grit::Config.new(repo)
Grit::Actor.new(config['user.name'], config['user.email'])
end
end
end
@last_actor
end
module ClassMethods
def process_hook(owner_uname, repo, newrev, oldrev, ref, newrev_type, oldrev_type)
rec = GitHook.new(owner_uname, repo, newrev, oldrev, ref, newrev_type, oldrev_type)
ActivityFeedObserver.instance.after_create rec
end
end
end
end
end

View File

@ -8,15 +8,8 @@ module Modules
after_create lambda { relations.create :actor_id => owner.id, :actor_type => owner.class.to_s, :role => 'admin' } after_create lambda { relations.create :actor_id => owner.id, :actor_type => owner.class.to_s, :role => 'admin' }
end end
module ClassMethods def name_with_owner
end "#{owner.respond_to?(:uname) ? owner.uname : owner.name}/#{self.name}"
module InstanceMethods
def name_with_owner
"#{owner.respond_to?(:uname) ? owner.uname : owner.name}/#{self.name}"
end
end end
end end
end end

View File

@ -9,19 +9,25 @@ module Modules
end end
def create_personal_repository def create_personal_repository
pl = own_platforms.build begin
pl.owner = self pl = own_platforms.build
pl.name = "#{self.uname}_personal" pl.owner = self
pl.description = "#{self.uname}_personal" pl.name = "#{self.uname}_personal"
pl.platform_type = 'personal' pl.description = "#{self.uname}_personal"
pl.distrib_type = APP_CONFIG['distr_types'].first pl.platform_type = 'personal'
pl.visibility = 'open' pl.distrib_type = APP_CONFIG['distr_types'].first
pl.save! pl.visibility = 'open'
pl.save!
rep = pl.repositories.build rep = pl.repositories.build
rep.name = 'main' rep.name = 'main'
rep.description = 'main' rep.description = 'main'
rep.save! rep.save!
rescue Exception => e
pl.now_destroy rescue false
raise e
end
return true
end end
def personal_platform def personal_platform

View File

@ -0,0 +1,39 @@
# -*- encoding : utf-8 -*-
module Modules
module Models
module Wiki
extend ActiveSupport::Concern
included do
after_create :create_wiki
after_destroy :destroy_wiki
end
def wiki_path
build_path(wiki_repo_name)
end
def wiki_repo_name
File.join owner.uname, "#{name}.wiki"
end
protected
def create_wiki
if has_wiki && !FileTest.exist?(wiki_path)
Grit::Repo.init_bare(wiki_path)
wiki = Gollum::Wiki.new(wiki_path, {:base_path => Rails.application.routes.url_helpers.project_wiki_index_path(owner, self)})
wiki.write_page('Home', :markdown, I18n.t("wiki.seed.welcome_content"),
{:name => owner.name, :email => owner.email, :message => 'Initial commit'})
end
end
def destroy_wiki
FileUtils.rm_rf wiki_path
end
module ClassMethods
end
end
end
end

View File

@ -35,7 +35,7 @@ module Grack
def project def project
@project ||= begin @project ||= begin
uname, name = @env['PATH_INFO'].split('/')[1,2] uname, name = @env['PATH_INFO'].split('/')[1,2]
name.gsub!(/\.git$/, '').gsub!(/\.wiki$/, '') name.gsub!(/(\.wiki)?\.git$/, '')
Project.find_by_owner_and_name uname, name Project.find_by_owner_and_name uname, name
end end
end end

View File

@ -9,7 +9,7 @@ task :add_branch => :environment do
Platform.find_by_name(dst_branch).repositories.each do |r| Platform.find_by_name(dst_branch).repositories.each do |r|
say "=== Process #{r.name} repo" say "=== Process #{r.name} repo"
r.projects.find_each do |p| r.projects.find_each do |p|
next if p.branches.map(&:name).include?(dst_branch) next if p.repo.branches.map(&:name).include?(dst_branch)
say "===== Process #{p.name} project" say "===== Process #{p.name} project"
tmp_path = Rails.root.join('tmp', p.name) tmp_path = Rails.root.join('tmp', p.name)
system("git clone #{p.path} #{tmp_path}") system("git clone #{p.path} #{tmp_path}")

View File

@ -0,0 +1,124 @@
require 'spec_helper'
describe Admin::FlashNotifiesController do
before(:each) do
stub_symlink_methods
@user = FactoryGirl.create(:user)
@create_params = {
:flash_notify => {
:body_ru => "Hello! I`m ru body",
:body_en => "Hello! I`m en body",
:status => "error",
:published => true
}
}
@flash_notify = FactoryGirl.create(:flash_notify)
@flash_notify2 = FactoryGirl.create(:flash_notify)
@update_params = {
:id => @flash_notify,
:flash_notify => {
:body_ru => "updated!"
}
}
end
context 'for guest' do
[:index, :create, :update, :edit, :new, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @flash_notify
response.should redirect_to(new_user_session_path)
end
end
it 'should not change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0)
end
it 'should not change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(0)
end
it 'should not change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should_not == "updated!"
end
end
context 'for global admin' do
before(:each) do
@admin = FactoryGirl.create(:admin)
@user = FactoryGirl.create(:user)
set_session_for(@admin)
end
it 'should load 2 flash notifies objects on index' do
get :index
assigns[:flash_notifies].count.should == 2
end
[:index, :new, :edit].each do |action|
it "should be able to perform #{action} action" do
get action, :id => @flash_notify
response.should render_template(action)
end
end
it 'should be able to perform create action' do
post :create, @create_params
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(1)
end
it 'should be able to perform destroy action' do
delete :destroy, :id => @flash_notify
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(-1)
end
it 'should be able to perform update action' do
put :update, @update_params
response.should redirect_to(admin_flash_notifies_path)
end
it 'should change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should == "updated!"
end
end
context 'for simple user' do
before(:each) do
@user = FactoryGirl.create(:user)
set_session_for(@user)
end
[:index, :create, :update, :edit, :new, :destroy].each do |action|
it "should not be able to perform #{ action } action" do
get action, :id => @flash_notify
response.should redirect_to(forbidden_path)
end
end
it 'should not change objects count on create' do
lambda { post :create, @create_params }.should change{ FlashNotify.count }.by(0)
end
it 'should not change objects count on destroy' do
lambda { delete :destroy, :id => @flash_notify }.should change{ FlashNotify.count }.by(0)
end
it 'should not change flash notify body on update' do
put :update, @update_params
@flash_notify.reload.body_ru.should_not == "updated!"
end
end
end

View File

@ -76,6 +76,7 @@ describe Platforms::MassBuildsController do
before(:each) do before(:each) do
stub_symlink_methods stub_symlink_methods
FactoryGirl.create(:arch)
@platform = FactoryGirl.create(:platform) @platform = FactoryGirl.create(:platform)
@repository = FactoryGirl.create(:repository, :platform => @platform) @repository = FactoryGirl.create(:repository, :platform => @platform)
@personal_platform = FactoryGirl.create(:platform, :platform_type => 'personal') @personal_platform = FactoryGirl.create(:platform, :platform_type => 'personal')
@ -91,13 +92,23 @@ describe Platforms::MassBuildsController do
end end
context 'for guest' do context 'for guest' do
[:index, :create, :cancel, :failed_builds_list].each do |action| [:index, :create].each do |action|
it "should not be able to perform #{ action } action" do it "should not be able to perform #{ action } action" do
get action, :platform_id => @platform get action, :platform_id => @platform
response.should redirect_to(new_user_session_path) response.should redirect_to(new_user_session_path)
end end
end end
it "should not be able to perform failed_builds_list action" do
get :failed_builds_list, :platform_id => @platform, :id => @mass_build
response.should redirect_to(new_user_session_path)
end
it "should not be able to perform cancel action" do
post :cancel, :platform_id => @platform, :id => @mass_build
response.should redirect_to(new_user_session_path)
end
it 'should not change objects count on create success' do it 'should not change objects count on create success' do
lambda { post :create, @create_params }.should change{ MassBuild.count }.by(0) lambda { post :create, @create_params }.should change{ MassBuild.count }.by(0)
end end

View File

@ -32,7 +32,7 @@ end
shared_examples_for 'registered user' do shared_examples_for 'registered user' do
it 'should be able to perform index action' do it 'should be able to perform index action' do
get :index get :index, :platform_id => @platform.id
response.should render_template(:index) response.should render_template(:index)
end end
@ -80,7 +80,7 @@ describe Platforms::RepositoriesController do
context 'for guest' do context 'for guest' do
[:index, :create].each do |action| [:index, :create].each do |action|
it "should not be able to perform #{ action } action" do it "should not be able to perform #{ action } action" do
get action get action, :platform_id => @platform
response.should redirect_to(new_user_session_path) response.should redirect_to(new_user_session_path)
end end
end end

View File

@ -42,13 +42,13 @@ describe Projects::BuildListsController do
it 'should save correct commit_hash for branch based build' do it 'should save correct commit_hash for branch based build' do
post :create, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@create_params).deep_merge(:build_list => {:project_version => "latest_master"}) post :create, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@create_params).deep_merge(:build_list => {:project_version => "latest_master"})
@project.build_lists.last.commit_hash.should == @project.git_repository.commits('master').last.id @project.build_lists.last.commit_hash.should == @project.repo.commits('master').last.id
end end
it 'should save correct commit_hash for tag based build' do it 'should save correct commit_hash for tag based build' do
system("cd #{@project.git_repository.path} && git tag 4.7.5.3") # TODO REDO through grit system("cd #{@project.repo.path} && git tag 4.7.5.3") # TODO REDO through grit
post :create, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@create_params).deep_merge(:build_list => {:project_version => "4.7.5.3"}) post :create, {:owner_name => @project.owner.uname, :project_name => @project.name}.merge(@create_params).deep_merge(:build_list => {:project_version => "4.7.5.3"})
@project.build_lists.last.commit_hash.should == @project.git_repository.commits('4.7.5.3').last.id @project.build_lists.last.commit_hash.should == @project.repo.commits('4.7.5.3').last.id
end end
end end
@ -283,7 +283,7 @@ describe Projects::BuildListsController do
@build_list1 = FactoryGirl.create(:build_list_core) @build_list1 = FactoryGirl.create(:build_list_core)
@build_list2 = FactoryGirl.create(:build_list_core) @build_list2 = FactoryGirl.create(:build_list_core)
@build_list3 = FactoryGirl.create(:build_list_core) @build_list3 = FactoryGirl.create(:build_list_core)
@build_list4 = FactoryGirl.create(:build_list_core, :created_at => (Time.now - 1.day), @build_list4 = FactoryGirl.create(:build_list_core, :updated_at => (Time.now - 1.day),
:project => @build_list3.project, :save_to_platform => @build_list3.save_to_platform, :project => @build_list3.project, :save_to_platform => @build_list3.save_to_platform,
:arch => @build_list3.arch) :arch => @build_list3.arch)
end end
@ -305,9 +305,9 @@ describe Projects::BuildListsController do
it 'should filter by project_name and start_date' do it 'should filter by project_name and start_date' do
get :index, :filter => {:project_name => @build_list3.project.name, :ownership => 'index', get :index, :filter => {:project_name => @build_list3.project.name, :ownership => 'index',
"created_at_start(1i)" => @build_list3.created_at.year.to_s, :"updated_at_start(1i)" => @build_list3.updated_at.year.to_s,
"created_at_start(2i)" => @build_list3.created_at.month.to_s, :"updated_at_start(2i)" => @build_list3.updated_at.month.to_s,
"created_at_start(3i)" => @build_list3.created_at.day.to_s} :"updated_at_start(3i)" => @build_list3.updated_at.day.to_s}
assigns[:build_lists].should_not include(@build_list1) assigns[:build_lists].should_not include(@build_list1)
assigns[:build_lists].should_not include(@build_list2) assigns[:build_lists].should_not include(@build_list2)
assigns[:build_lists].should include(@build_list3) assigns[:build_lists].should include(@build_list3)
@ -326,7 +326,7 @@ describe Projects::BuildListsController do
describe 'publish_build' do describe 'publish_build' do
before { before {
test_git_commit(build_list.project) test_git_commit(build_list.project)
build_list.update_attribute :commit_hash, build_list.project.git_repository.commits('master').last.id build_list.update_attribute :commit_hash, build_list.project.repo.commits('master').last.id
build_list.update_attribute(:status, BuildList::BUILD_PUBLISH) build_list.update_attribute(:status, BuildList::BUILD_PUBLISH)
build_list_package build_list_package
} }
@ -343,8 +343,8 @@ describe Projects::BuildListsController do
} }
it 'should create correct git tag for correct commit' do it 'should create correct git tag for correct commit' do
do_get(BuildServer::SUCCESS) do_get(BuildServer::SUCCESS)
build_list.project.git_repository.tags.last.name.should == build_list.package_version build_list.project.repo.tags.last.name.should == build_list.package_version
build_list.project.git_repository.commits(build_list.package_version).last.id.should == build_list.commit_hash build_list.project.repo.commits(build_list.package_version).last.id.should == build_list.commit_hash
end end
it(:passes) { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :status).to(BuildList::BUILD_PUBLISHED) } it(:passes) { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :status).to(BuildList::BUILD_PUBLISHED) }
it(:passes) { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :package_version).to("#{ build_list_package.platform.name }-4.7.5.3-1") } it(:passes) { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :package_version).to("#{ build_list_package.platform.name }-4.7.5.3-1") }

View File

@ -78,8 +78,8 @@ describe Projects::CommentsController do
before(:each) do before(:each) do
stub_symlink_methods stub_symlink_methods
@project = FactoryGirl.create(:project) @project = FactoryGirl.create(:project)
%x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ? %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.repo.path}) # maybe FIXME ?
@commit = @project.git_repository.commits.first @commit = @project.repo.commits.first
@create_params = {:comment => {:body => 'I am a comment!'}, :owner_name => @project.owner.uname, :project_name => @project.name, :commit_id => @commit.id} @create_params = {:comment => {:body => 'I am a comment!'}, :owner_name => @project.owner.uname, :project_name => @project.name, :commit_id => @commit.id}
@update_params = {:comment => {:body => 'updated'}, :owner_name => @project.owner.uname, :project_name => @project.name, :commit_id => @commit.id} @update_params = {:comment => {:body => 'updated'}, :owner_name => @project.owner.uname, :project_name => @project.name, :commit_id => @commit.id}

View File

@ -4,7 +4,7 @@ require 'spec_helper'
describe Projects::Git::TreesController do describe Projects::Git::TreesController do
def fill_project def fill_project
%x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ? %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.repo.path}) # maybe FIXME ?
end end
before(:each) do before(:each) do
@ -12,7 +12,7 @@ describe Projects::Git::TreesController do
@project = FactoryGirl.create(:project) @project = FactoryGirl.create(:project)
@another_user = FactoryGirl.create(:user) @another_user = FactoryGirl.create(:user)
@params = {:owner_name => @project.owner.uname, :project_name => @project.name} @params = {:owner_name => @project.owner.uname, :project_name => @project.name, :treeish => 'master'}
end end
context 'for guest' do context 'for guest' do
@ -35,21 +35,21 @@ describe Projects::Git::TreesController do
it 'should not be able to archive empty project' do it 'should not be able to archive empty project' do
@user = FactoryGirl.create(:user) @user = FactoryGirl.create(:user)
set_session_for(@user) set_session_for(@user)
expect { get :archive, @params.merge(:format => 'tar') }.to raise_error(ActiveRecord::RecordNotFound) expect { get :archive, @params.merge(:format => 'tar') }.to raise_error(ActionController::RoutingError)
end end
it 'should not be able to injection code with format' do it 'should not be able to injection code with format' do
@user = FactoryGirl.create(:user) @user = FactoryGirl.create(:user)
set_session_for(@user) set_session_for(@user)
fill_project fill_project
expect { get :archive, @params.merge(:format => "tar master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActiveRecord::RecordNotFound) expect { get :archive, @params.merge(:format => "tar master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActionController::RoutingError)
end end
it 'should not be able to injection code with treeish' do it 'should not be able to injection code with treeish' do
@user = FactoryGirl.create(:user) @user = FactoryGirl.create(:user)
set_session_for(@user) set_session_for(@user)
fill_project fill_project
expect { get :archive, @params.merge(:treeish => "master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActiveRecord::RecordNotFound) expect { get :archive, @params.merge(:treeish => "master > /dev/null; echo 'I am hacker!';\#") }.to raise_error(ActionController::RoutingError)
end end
it 'should be able to perform archive action' do it 'should be able to perform archive action' do

View File

@ -16,7 +16,7 @@ describe Users::ProfileController do
context 'for guest' do context 'for guest' do
it 'should not be able to view profile' do it 'should not be able to view profile' do
get :show, :owner_name => @simple_user.uname get :show, :uname => @simple_user.uname
response.should redirect_to(new_user_session_path) response.should redirect_to(new_user_session_path)
end end
end end

View File

@ -0,0 +1,10 @@
# -*- encoding : utf-8 -*-
FactoryGirl.define do
factory :flash_notify do
body_ru { FactoryGirl.generate(:string) }
body_en { FactoryGirl.generate(:string) }
status "error"
published true
end
end

View File

@ -8,7 +8,7 @@ FactoryGirl.define do
association :owner, :factory => :user association :owner, :factory => :user
factory :platform_with_repos do factory :platform_with_repos do
after_create {|p| FactoryGirl.create_list(:repository, 1, platform: p)} after(:create) {|p| FactoryGirl.create_list(:repository, 1, platform: p)}
end end
factory :personal_platform do factory :personal_platform do

View File

@ -10,8 +10,8 @@ def set_comments_data_for_commit
@ability = Ability.new(@user) @ability = Ability.new(@user)
@project = FactoryGirl.create(:project, :owner => @user) @project = FactoryGirl.create(:project, :owner => @user)
%x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ? %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.repo.path}) # maybe FIXME ?
@commit = @project.git_repository.commits.first @commit = @project.repo.commits.first
@comment = create_comment(@user) @comment = create_comment(@user)
@stranger_comment = create_comment(@stranger) @stranger_comment = create_comment(@stranger)

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe FlashNotify do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -1,6 +1,41 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
require 'spec_helper' require 'spec_helper'
#describe Project do describe Project do
# pending "add some examples to (or delete) #{__FILE__}" before(:each) do
#end stub_symlink_methods
@root_project = FactoryGirl.create(:project)
@child_project = @root_project.fork(FactoryGirl.create(:user))
@child_child_project = @child_project.fork(FactoryGirl.create(:user))
end
context 'for destroy root' do
before(:each) do
@root_project.destroy
end
it "should not be delete child" do
Project.where(:id => @child_project).count.should == 1
end
it "should not be delete child of the child" do
Project.where(:id => @child_child_project).count.should == 1
end
end
# uncommit when will be available :orphan_strategy => :adopt
#context 'for destroy middle node' do
# before(:each) do
# @child_project.destroy
# end
# it "should set root project as a parent for orphan child" do
# Project.find(@child_child_project).ancestry == @root_project
# end
# it "should not be delete child of the child" do
# Project.where(:id => @child_child_project).count.should == 1
# end
#end
end

View File

@ -13,7 +13,7 @@ describe Projects::ProjectsController do
end end
it "routes to #edit" do it "routes to #edit" do
get("/import/glib2.0-mib/edit").should route_to("projects/projects#edit", :owner_name => 'import', :project_name => 'glib2.0-mib') get("/import/glib2.0-mib/modify").should route_to("projects/projects#edit", :owner_name => 'import', :project_name => 'glib2.0-mib')
end end
it "routes to #create" do it "routes to #create" do
@ -39,6 +39,8 @@ describe Projects::Git::TreesController do
get("/import/glib2.0-mib/tree/lib2safe-0.03").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'lib2safe-0.03') get("/import/glib2.0-mib/tree/lib2safe-0.03").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'lib2safe-0.03')
get("/import/glib2.0-mib/tree/branch-with.dot/folder_with.dot/path-with.dot").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'branch-with.dot', :path => 'folder_with.dot/path-with.dot') get("/import/glib2.0-mib/tree/branch-with.dot/folder_with.dot/path-with.dot").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'branch-with.dot', :path => 'folder_with.dot/path-with.dot')
# get("/import/glib2.0-mib/tree/ветка-с.точкой/папка_с.точкой/путь-с.точкой").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'ветка-с.точкой', :path => 'папка_с.точкой/путь-с.точкой') # get("/import/glib2.0-mib/tree/ветка-с.точкой/папка_с.точкой/путь-с.точкой").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'ветка-с.точкой', :path => 'папка_с.точкой/путь-с.точкой')
get("/import/glib2.0-mib/tree/branch-with/slash.dot/folder_with.dot/path-with.dot").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'branch-with/slash.dot', :path => 'folder_with.dot/path-with.dot')
get("/import/glib2.0-mib/tree/tag13.52-5").should route_to("projects/git/trees#show", :owner_name => 'import', :project_name => 'glib2.0-mib', :treeish => 'tag13.52-5')
end end
# TODO write more specs also with slash in branch name! # TODO write more specs also with slash in branch name!

View File

@ -39,8 +39,8 @@ def stub_symlink_methods
end end
def test_git_commit(project) def test_git_commit(project)
project.git_repository.repo.index.add('test', 'TEST') project.repo.index.add('test', 'TEST')
project.git_repository.repo.index.commit('Test commit') project.repo.index.commit('Test commit')
end end
Resque.inline = true Resque.inline = true

View File

@ -0,0 +1,90 @@
/* ==========================================================
* bootstrap-alert.js v2.0.4
* http://twitter.github.com/bootstrap/javascript.html#alerts
* ==========================================================
* Copyright 2012 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ========================================================== */
!function ($) {
"use strict"; // jshint ;_;
/* ALERT CLASS DEFINITION
* ====================== */
var dismiss = '[data-dismiss="alert"]'
, Alert = function (el) {
$(el).on('click', dismiss, this.close)
}
Alert.prototype.close = function (e) {
var $this = $(this)
, selector = $this.attr('data-target')
, $parent
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
$parent = $(selector)
e && e.preventDefault()
$parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
$parent.trigger(e = $.Event('close'))
if (e.isDefaultPrevented()) return
$parent.removeClass('in')
function removeElement() {
$parent
.trigger('closed')
.remove()
}
$.support.transition && $parent.hasClass('fade') ?
$parent.on($.support.transition.end, removeElement) :
removeElement()
}
/* ALERT PLUGIN DEFINITION
* ======================= */
$.fn.alert = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('alert')
if (!data) $this.data('alert', (data = new Alert(this)))
if (typeof option == 'string') data[option].call($this)
})
}
$.fn.alert.Constructor = Alert
/* ALERT DATA-API
* ============== */
$(function () {
$('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
})
}(window.jQuery);

View File

@ -13,6 +13,7 @@
//= require bootstrap-tab //= require bootstrap-tab
// require bootstrap-tooltip // require bootstrap-tooltip
// require bootstrap-popover // require bootstrap-popover
//= require bootstrap-alert
//= require chosen.jquery //= require chosen.jquery
// require html5shiv // require html5shiv
// require_tree . // require_tree .