diff --git a/Gemfile b/Gemfile
index 4076c4e09..7076e5e1b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,7 +18,7 @@ gem "yui-compressor", "0.9.5" # Higher versions depends on Platform gem which co
gem 'rails3-jquery-autocomplete'
gem 'ancestry', '~> 1.2.4'
-gem 'paperclip', "~> 2.3"
+gem 'paperclip', "~> 2.5"
gem "will_paginate", "~> 3.0.2"
gem 'meta-tags', '~> 1.2.4', :require => 'meta_tags'
gem "russian"
@@ -43,7 +43,7 @@ gem 'unicorn', '~> 4.1.1'
group :production do
gem "airbrake", '~> 3.0.5'
- # gem 'newrelic_rpm', '~> 3.1.1'
+ gem 'newrelic_rpm'
gem 'bluepill', :require => false
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 9819287e4..5fee68804 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -61,7 +61,7 @@ GEM
capistrano (>= 1.0.0)
capistrano_colors (0.5.5)
chronic (0.6.6)
- cocaine (0.2.0)
+ cocaine (0.2.1)
columnize (0.3.5)
daemons (1.1.4)
delayed_job (2.1.4)
@@ -127,6 +127,7 @@ GEM
net-ssh-gateway (1.1.0)
net-ssh (>= 1.99.1)
nokogiri (1.5.0)
+ newrelic_rpm (3.3.1)
omniauth (1.0.1)
hashie (~> 1.2)
rack
@@ -134,7 +135,7 @@ GEM
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
orm_adapter (0.0.5)
- paperclip (2.4.5)
+ paperclip (2.5.0)
activerecord (>= 2.3.0)
activesupport (>= 2.3.2)
cocaine (>= 0.0.2)
@@ -251,9 +252,10 @@ DEPENDENCIES
jammit
meta-tags (~> 1.2.4)
mysql2 (<= 0.2.9)
+ newrelic_rpm
omniauth (~> 1.0.1)
omniauth-openid (~> 1.0.1)
- paperclip (~> 2.3)
+ paperclip (~> 2.5)
pg (~> 0.11.0)
rails (= 3.0.11)
rails-xmlrpc (~> 0.3.6)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 4a64259cd..494f54ae1 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,8 +1,10 @@
# coding: UTF-8
class ApplicationController < ActionController::Base
protect_from_forgery
+
layout :layout_by_resource
+ before_filter :set_locale
before_filter lambda { EventLog.current_controller = self },
:only => [:create, :destroy, :open_id, :auto_build, :cancel, :publish, :change_visibility] # :update
after_filter lambda { EventLog.current_controller = nil }
@@ -14,26 +16,39 @@ class ApplicationController < ActionController::Base
end
protected
- def get_owner
+
+ def set_locale
+ I18n.locale = check_locale( get_user_locale || request.env['HTTP_ACCEPT_LANGUAGE'] )
+ end
+
+ def get_user_locale
+ user_signed_in? ? current_user.language : nil
+ end
+
+ def check_locale(locale)
+ User::LANGUAGES.include?(locale.to_s) ? locale : :en
+ end
+
+ def get_owner
# params['user_id'] && User.find_by_id(params['user_id']) ||
# params['group_id'] && Group.find_by_id(params['group_id']) || current_user
- if self.class.method_defined? :parent
- if parent and (parent.is_a? User or parent.is_a? Group)
- return parent
- else
- return current_user
- end
+ if self.class.method_defined? :parent
+ if parent and (parent.is_a? User or parent.is_a? Group)
+ return parent
else
- params['user_id'] && User.find_by_id(params['user_id']) ||
- params['group_id'] && Group.find_by_id(params['group_id']) || current_user
+ return current_user
end
+ else
+ params['user_id'] && User.find_by_id(params['user_id']) ||
+ params['group_id'] && Group.find_by_id(params['group_id']) || current_user
end
+ end
- def layout_by_resource
- if devise_controller?
- "sessions"
- else
- "application"
- end
+ def layout_by_resource
+ if devise_controller?
+ "sessions"
+ else
+ "application"
end
+ end
end
diff --git a/app/controllers/build_lists_controller.rb b/app/controllers/build_lists_controller.rb
index fc650a4b3..29d869151 100644
--- a/app/controllers/build_lists_controller.rb
+++ b/app/controllers/build_lists_controller.rb
@@ -39,6 +39,7 @@ class BuildListsController < ApplicationController
Arch.where(:id => params[:arches]).each do |arch|
Platform.main.where(:id => params[:bpls]).each do |bpl|
@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
@build_list.bpl = bpl; @build_list.arch = arch; @build_list.user = current_user
flash_options = {:project_version => @build_list.project_version, :arch => arch.name, :bpl => bpl.name, :pl => @build_list.pl}
if @build_list.save
@@ -80,7 +81,13 @@ class BuildListsController < ApplicationController
end
def publish_build
- @build_list.status = (params[:status].to_i == 0 ? BuildList::BUILD_PUBLISHED : BuildList::FAILED_PUBLISH)
+ if params[:status].to_i == 0 # ok
+ @build_list.status = BuildList::BUILD_PUBLISHED
+ @build_list.package_version = "#{params[:version]}-#{params[:release]}"
+ system("cd #{@build_list.project.git_repository.path} && git tag #{@build_list.package_version} #{@build_list.commit_hash}") # TODO REDO through grit
+ else
+ @build_list.status = BuildList::FAILED_PUBLISH
+ end
@build_list.notified_at = Time.current
@build_list.save
@@ -113,9 +120,9 @@ class BuildListsController < ApplicationController
@build_list.notified_at = Time.current
@build_list.save
- @build_list.delay.publish if @build_list.auto_publish # && @build_list.can_publish?
-
render :nothing => true, :status => 200
+
+ @build_list.delay.publish if @build_list.auto_publish # && @build_list.can_publish?
end
def circle_build
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index e20aa3af1..6f699a602 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -1,7 +1,7 @@
class CommentsController < ApplicationController
before_filter :authenticate_user!
- before_filter :set_commentable, :only => [:index, :edit, :create]
- before_filter :find_project, :only => [:index]
+ before_filter :set_commentable, :only => [:index, :edit, :create, :update, :destroy]
+ #before_filter :find_project, :only => [:index, :edit]
before_filter :find_comment, :only => [:edit, :update, :destroy]
authorize_resource :only => [:show, :edit, :update, :destroy]
@@ -12,11 +12,12 @@ class CommentsController < ApplicationController
end
def create
- @comment = @commentable.comments.build(params[:comment])
+ @comment = @commentable.comments.build(params[:comment]) if @commentable.class == Issue
+ @comment = Comment.new(params[:comment].merge(:commentable_id => @commentable.id, :commentable_type => @commentable.class.name)) if @commentable.class == Grit::Commit
@comment.user = current_user
if @comment.save
flash[:notice] = I18n.t("flash.comment.saved")
- redirect_to :back
+ redirect_to commentable_path
else
flash[:error] = I18n.t("flash.comment.save_error")
render :action => 'new'
@@ -24,15 +25,19 @@ class CommentsController < ApplicationController
end
def edit
- @issue = @commentable
- @project = @issue.project
+ @update_url = case @commentable.class.name
+ when "Issue"
+ project_issue_comment_path(@project, @commentable, @comment)
+ when "Grit::Commit"
+ project_commit_comment_path(@project, @commentable, @comment)
+ end
+ @commentable_path = commentable_path
end
def update
if @comment.update_attributes(params[:comment])
flash[:notice] = I18n.t("flash.comment.saved")
- #redirect_to :back
- redirect_to [@comment.commentable.project, @comment.commentable]
+ redirect_to commentable_path
else
flash[:error] = I18n.t("flash.comment.save_error")
render :action => 'new'
@@ -43,7 +48,7 @@ class CommentsController < ApplicationController
@comment.destroy
flash[:notice] = t("flash.comment.destroyed")
- redirect_to :back
+ redirect_to commentable_path
end
private
@@ -55,18 +60,31 @@ class CommentsController < ApplicationController
# end
#end
#nil
- return Issue.find(params[:issue_id])
+ if params[:issue_id].present?
+ return Issue.find_by_serial_id_and_project_id(params[:issue_id], params[:project_id])
+ elsif params[:commit_id].present?
+ return @project.git_repository.commit(params[:commit_id])
+ end
end
def set_commentable
+ find_project
@commentable = find_commentable
end
def find_comment
@comment = Comment.find(params[:id])
+ @comment.project = @project if @comment.commentable_type == 'Grit::Commit'
end
def find_project
- @project = @comment.commentable.project
+ @project = Project.find(params[:project_id])
end
+
+ protected
+
+ def commentable_path
+ @commentable.class == Issue ? [@project, @commentable] : commit_path(@project, @commentable.id)
+ end
+
end
diff --git a/app/controllers/git/blobs_controller.rb b/app/controllers/git/blobs_controller.rb
index 1182412ea..eb788d211 100644
--- a/app/controllers/git/blobs_controller.rb
+++ b/app/controllers/git/blobs_controller.rb
@@ -5,6 +5,16 @@ class Git::BlobsController < Git::BaseController
def show
@blob = @tree / @path
+
+ if params[:raw]
+ image_url = Rails.root.to_s + "/" + @path
+
+ 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 => open(image_url).read) and return
+ end
end
def blame
@@ -42,4 +52,4 @@ class Git::BlobsController < Git::BaseController
@commit = @git_repository.log(@treeish, @path).first # TODO WTF nil ?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/git/commits_controller.rb b/app/controllers/git/commits_controller.rb
index 04b1a94dc..021d60cee 100644
--- a/app/controllers/git/commits_controller.rb
+++ b/app/controllers/git/commits_controller.rb
@@ -23,4 +23,4 @@ class Git::CommitsController < Git::BaseController
end
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 3f1a6f4ec..99f13be95 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -30,7 +30,10 @@ class IssuesController < ApplicationController
@issue = Issue.new(params[:issue])
@issue.user_id = @user_id
@issue.project_id = @project.id
+
if @issue.save
+ @issue.subscribe_creator(current_user.id)
+
flash[:notice] = I18n.t("flash.issue.saved")
redirect_to project_issues_path(@project)
else
@@ -41,12 +44,12 @@ class IssuesController < ApplicationController
def edit
@user_id = @issue.user_id
- @user_uname = @issue.user.uname
+ @user_uname = @issue.assign_uname
end
def update
@user_id = params[:user_id].blank? ? @issue.user_id : params[:user_id]
- @user_uname = params[:user_uname].blank? ? @issue.user.uname : params[:user_uname]
+ @user_uname = params[:user_uname].blank? ? @issue.assign_uname : params[:user_uname]
if @issue.update_attributes( params[:issue].merge({:user_id => @user_id}) )
flash[:notice] = I18n.t("flash.issue.saved")
diff --git a/app/controllers/platforms_controller.rb b/app/controllers/platforms_controller.rb
index 3ce47f9a7..9c9563e02 100644
--- a/app/controllers/platforms_controller.rb
+++ b/app/controllers/platforms_controller.rb
@@ -113,7 +113,7 @@ class PlatformsController < ApplicationController
@cloned = @platform.make_clone(:name => params[:platform]['name'], :description => params[:platform]['description'],
:owner_id => current_user.id, :owner_type => current_user.class.to_s)
if @cloned.persisted?
- flash[:notice] = 'Клонирование успешно'
+ flash[:notice] = I18n.t("flash.platform.clone_success")
redirect_to @cloned
else
flash[:error] = @cloned.errors.full_messages.join('. ')
diff --git a/app/controllers/settings/notifiers_controller.rb b/app/controllers/settings/notifiers_controller.rb
new file mode 100644
index 000000000..03df52237
--- /dev/null
+++ b/app/controllers/settings/notifiers_controller.rb
@@ -0,0 +1,22 @@
+class Settings::NotifiersController < ApplicationController
+ layout "sessions"
+
+ before_filter :authenticate_user!
+
+ load_and_authorize_resource :user
+ load_and_authorize_resource :class => Settings::Notifier, :through => :user, :singleton => true, :shallow => true
+
+ def show
+ end
+
+ def update
+ if @notifier.update_attributes(params[:settings_notifier])
+ flash[:notice] = I18n.t("flash.settings.saved")
+ redirect_to [@user, @notifier]
+ else
+ flash[:notice] = I18n.t("flash.settings.save_error")
+ redirect_to [@user, @notifier]
+ end
+ end
+
+end
diff --git a/app/helpers/git_helper.rb b/app/helpers/git_helper.rb
index 8dd3624ad..286fba6f2 100644
--- a/app/helpers/git_helper.rb
+++ b/app/helpers/git_helper.rb
@@ -40,4 +40,9 @@ module GitHelper
blob.data.split("\n").collect{|line| "
#{line.present? ? h(line) : "
"}
"}.join
end
-end
\ No newline at end of file
+ def choose_render_way(blob)
+ return :image if blob.mime_type.match(/image/)
+ return :text if blob.mime_type.match(/text|xml|json/)
+ :binary
+ end
+end
diff --git a/app/helpers/settings/notifiers_helper.rb b/app/helpers/settings/notifiers_helper.rb
new file mode 100644
index 000000000..295af1e51
--- /dev/null
+++ b/app/helpers/settings/notifiers_helper.rb
@@ -0,0 +1,2 @@
+module Settings::NotifiersHelper
+end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 2c43482e1..39ceffa17 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -1,7 +1,7 @@
# coding: UTF-8
class UserMailer < ActionMailer::Base
- default :from => APP_CONFIG['no-reply-email']
+ default :from => APP_CONFIG['do-not-reply-email']
def new_user_notification(user)
@user = user
@@ -18,6 +18,14 @@ class UserMailer < ActionMailer::Base
end
end
+ def new_comment_reply_notification(comment, user)
+ @user = user
+ @comment = comment
+ mail(:to => user.email, :subject => I18n.t("notifications.subjects.new_comment_reply_notification")) do |format|
+ format.html
+ end
+ end
+
def new_issue_notification(issue, user)
@user = user
@issue = issue
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 1b7509a2b..7709990ee 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -1,8 +1,8 @@
# If rules goes one by one CanCan joins them by 'OR' sql operator
# If rule has multiple conditions CanCan joins them by 'AND' sql operator
-# WARNING:
+# WARNING:
# - put cannot rules _after_ can rules and not before!
-# - beware inner joins. Use sub queries against them!
+# - beware inner joins. Use sub queries against them!
class Ability
include CanCan::Ability
@@ -28,6 +28,8 @@ class Ability
else # Registered user rights
can [:show, :autocomplete_user_uname], User
+ can [:show, :update], Settings::Notifier, :user_id => user.id
+
can [:read, :create], Group
can [:update, :manage_members], Group do |group|
group.objects.exists?(:object_type => 'User', :object_id => user.id, :role => 'admin') # or group.owner_id = user.id
@@ -44,8 +46,9 @@ class Ability
can(:fork, Project) {|project| can? :read, project}
can(:destroy, Project) {|project| owner? project}
- can :create, AutoBuildList
- can [:index, :destroy], AutoBuildList, :project_id => user.own_project_ids
+ # TODO: Turn on AAA when it will be updated
+ #can :create, AutoBuildList
+ #can [:index, :destroy], AutoBuildList, :project_id => user.own_project_ids
can :read, BuildList, :project => {:visibility => 'open'}
can :read, BuildList, :project => {:owner_type => 'User', :owner_id => user.id}
@@ -89,9 +92,10 @@ class Ability
can([:update, :destroy], Issue) {|issue| issue.user_id == user.id or local_admin?(issue.project)}
cannot :manage, Issue, :project => {:has_issues => false} # switch off issues
- can(:create, Comment) {|comment| can? :read, comment.commentable.project}
- can(:update, Comment) {|comment| comment.user_id == user.id or local_admin?(comment.commentable.project)}
- cannot :manage, Comment, :commentable => {:project => {:has_issues => false}} # switch off issues
+ can(:create, Comment) {|comment| can? :read, comment.project || comment.commentable.project}
+ can(:update, Comment) {|comment| comment.user_id == user.id or local_admin?(comment.project || comment.commentable.project)}
+ #cannot :manage, Comment, :commentable => {:project => {:has_issues => false}} # switch off issues
+ cannot(:manage, Comment) {|comment| comment.commentable_type == 'Issue' && !comment.commentable.project.has_issues} # switch off issues
end
end
diff --git a/app/models/build_list/item.rb b/app/models/build_list/item.rb
index a06e3b89e..ec49f740c 100644
--- a/app/models/build_list/item.rb
+++ b/app/models/build_list/item.rb
@@ -1,11 +1,15 @@
class BuildList::Item < ActiveRecord::Base
+
belongs_to :build_list
attr_protected :build_list_id
- STATUSES = [BuildServer::SUCCESS, BuildServer::DEPENDENCIES_ERROR, BuildServer::BUILD_ERROR, BuildServer::BUILD_STARTED]
+ GIT_ERROR = 5
+
+ STATUSES = [BuildServer::SUCCESS, BuildServer::DEPENDENCIES_ERROR, BuildServer::BUILD_ERROR, BuildServer::BUILD_STARTED, GIT_ERROR]
HUMAN_STATUSES = {
nil => :unknown,
+ GIT_ERROR => :git_error,
BuildServer::DEPENDENCIES_ERROR => :dependencies_error,
BuildServer::SUCCESS => :success,
BuildServer::BUILD_STARTED => :build_started,
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 439fd0733..8ba9c05d0 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,20 +1,30 @@
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
belongs_to :user
+ attr_accessor :project
validates :body, :user_id, :commentable_id, :commentable_type, :presence => true
- after_create :deliver_new_comment_notification
+ # FIXME
+ after_create :subscribe_on_reply, :unless => "commentable_type == 'Grit::Commit'"
+ after_create :deliver_new_comment_notification, :unless => "commentable_type == 'Grit::Commit'"
protected
def deliver_new_comment_notification
- recipients = self.commentable.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
- recipients = recipients | [self.commentable.user_id]
- recipients = recipients | [self.commentable.project.owner_id] if self.commentable.project.owner_type == 'User'
- recipients.each do |recipient_id|
- recipient = User.find(recipient_id)
- UserMailer.delay.new_comment_notification(self, recipient)
+ subscribes = self.commentable.subscribes
+ subscribes.each do |subscribe|
+ if self.user_id != subscribe.user_id && User.find(subscribe.user).notifier.new_comment_reply && User.find(subscribe.user).notifier.can_notify
+ if self.commentable.comments.exists?(:user_id => subscribe.user.id)
+ UserMailer.delay.new_comment_reply_notification(self, subscribe.user)
+ else
+ UserMailer.delay.new_comment_notification(self, subscribe.user)
+ end
+ end
end
end
+
+ def subscribe_on_reply
+ self.commentable.subscribes.create(:user_id => self.user_id) if !self.commentable.subscribes.exists?(:user_id => self.user_id)
+ end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 9ae96f439..efeffbf13 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -4,7 +4,13 @@ class Issue < ActiveRecord::Base
belongs_to :project
belongs_to :user
- has_many :comments, :as => :commentable
+ has_many :comments, :as => :commentable,
+ :finder_sql => proc { "comments.commentable_id = '#{self.id}' " +
+ " AND comments.commentable_type = '#{self.class.name}'"}
+ #'SELECT comments.* FROM comments ' +
+ #'WHERE comments.commentable_id = \'#{self.id}\' ' +
+ #' AND comments.commentable_type = \'#{self.class.name}\' ' +
+ #'ORDER BY comments.created_at'
has_many :subscribes, :as => :subscribeable
validates :title, :body, :project_id, :presence => true
@@ -16,6 +22,7 @@ class Issue < ActiveRecord::Base
after_create :deliver_new_issue_notification
after_create :deliver_issue_assign_notification
after_update :deliver_issue_assign_notification
+ after_update :subscribe_issue_assigned_user
def assign_uname
user.uname if user
@@ -25,6 +32,12 @@ class Issue < ActiveRecord::Base
serial_id.to_s
end
+ def subscribe_creator(creator_id)
+ if !self.subscribes.exists?(:user_id => creator_id)
+ self.subscribes.create(:user_id => creator_id)
+ end
+ end
+
protected
def set_serial_id
@@ -36,12 +49,12 @@ class Issue < ActiveRecord::Base
recipients = collect_recipient_ids
recipients.each do |recipient_id|
recipient = User.find(recipient_id)
- UserMailer.delay.new_issue_notification(self, recipient)#.deliver
+ UserMailer.delay.new_issue_notification(self, recipient) if User.find(recipient).notifier.can_notify && User.find(recipient).notifier.new_issue
end
end
def deliver_issue_assign_notification
- UserMailer.delay.issue_assign_notification(self, self.user) if self.user_id_was != self.user_id
+ UserMailer.delay.issue_assign_notification(self, self.user) if self.user_id_was != self.user_id && self.user.notifier.issue_assign && self.user.notifier.can_notify
end
def subscribe_users
@@ -56,7 +69,21 @@ class Issue < ActiveRecord::Base
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
recipients = recipients | [self.user_id] if self.user_id
recipients = recipients | [self.project.owner_id] if self.project.owner_type == 'User'
+
+ # filter by notification settings
+ recipients = recipients.select do |recipient|
+ User.find(recipient).notifier.new_issue && User.find(recipient).notifier.can_notify
+ end
+
recipients
end
+ def subscribe_issue_assigned_user
+ if self.user_id_was != self.user_id
+ self.subscribes.where(:user_id => self.user_id_was).first.destroy unless self.user_id_was.blank?
+ if self.user.notifier.issue_assign && !self.subscribes.exists?(:user_id => self.user_id)
+ self.subscribes.create(:user_id => self.user_id)
+ end
+ end
+ end
end
diff --git a/app/models/product.rb b/app/models/product.rb
index 36337f4f9..84afdfb35 100644
--- a/app/models/product.rb
+++ b/app/models/product.rb
@@ -9,7 +9,7 @@ class Product < ActiveRecord::Base
has_attached_file :tar
- validates_attachment_content_type :tar, :content_type => ["application/gnutar", "application/x-compressed", "application/x-gzip", "application/x-bzip2", "application/x-tar"], :message => I18n.t('layout.products.invalid_content_type')
+ validates_attachment_content_type :tar, :content_type => ["application/gnutar", "application/x-compressed", "application/x-gzip", "application/x-bzip2", "application/x-tar"], :message => I18n.t('layout.invalid_content_type')
validates :name, :presence => true, :uniqueness => {:scope => :platform_id}
scope :recent, order("name ASC")
diff --git a/app/models/project.rb b/app/models/project.rb
index 85ee5d513..8f8600ee3 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -9,6 +9,7 @@ class Project < ActiveRecord::Base
has_many :build_lists, :dependent => :destroy
has_many :auto_build_lists, :dependent => :destroy
+ # has_many :project_imports, :dependent => :destroy
has_many :project_to_repositories, :dependent => :destroy
has_many :repositories, :through => :project_to_repositories
@@ -20,6 +21,8 @@ class Project < ActiveRecord::Base
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, I18n.t('flash.project.save_warning_ssh_key')) if owner.ssh_key.blank?}
+ validates_attachment_size :srpm, :less_than => 500.megabytes
+ validates_attachment_content_type :srpm, :content_type => ['application/octet-stream'], :message => I18n.t('layout.invalid_content_type') # "application/x-rpm", "application/x-redhat-package-manager" ?
#attr_accessible :category_id, :name, :description, :visibility
attr_readonly :name
@@ -36,10 +39,13 @@ class Project < ActiveRecord::Base
after_destroy :destroy_git_repo
after_destroy :destroy_wiki
+ after_save {|p| p.delay.import_srpm if p.srpm?} # 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
def auto_build
@@ -59,10 +65,13 @@ class Project < ActiveRecord::Base
bl.pl = platform
bl.bpl = platform
bl.update_type = 'recommended'
- bl.arch = Arch.find_by_name('i586')
- bl.project_version = "latest_#{platform.name}"
+ bl.arch = Arch.find_by_name('x86_64') # Return i586 after mass rebuild
+ # FIXME: Need to set "latest_#{platform.name}"
+ bl.project_version = "latest_mandriva2011"
bl.build_requires = false # already set as db default
bl.user = user
+ bl.auto_publish = true # already set as db default
+ bl.include_repos = [platform.repositories.find_by_name('main').id]
end
end
@@ -71,7 +80,7 @@ class Project < ActiveRecord::Base
res = tags.select{|tag| tag.name =~ /^v\./}
return res if res and res.size > 0
tags
- end
+ end
def collected_project_versions
project_versions.collect{|tag| tag.name.gsub(/^\w+\./, "")}
end
@@ -127,7 +136,7 @@ class Project < ActiveRecord::Base
return true
else
raise "Failed to create project #{name} (repo #{repository.name}) inside platform #{repository.platform.name} in path #{path} with code #{result}."
- end
+ end
end
def xml_rpc_destroy(repository)
@@ -143,6 +152,20 @@ class Project < ActiveRecord::Base
@platforms ||= repositories.map(&:platform).uniq
end
+ def import_srpm(branch_name = 'import')
+ if srpm?
+ system("#{Rails.root.join('bin', 'import_srpm.sh')} #{srpm.path} #{path} #{branch_name} >> /dev/null 2>&1")
+ self.srpm = nil; save # clear srpm
+ end
+ end
+
+ class << self
+ def commit_comments(commit, project)
+ comments = Comment.where(:commentable_id => commit.id, :commentable_type => 'Grit::Commit').order(:created_at)
+ comments.each {|x| x.project = project}
+ end
+ end
+
protected
def build_path(dir)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 13c4e2a02..b9246f86a 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -48,7 +48,7 @@ class Repository < ActiveRecord::Base
return true
else
raise "Failed to create repository #{name} inside platform #{platform.name} with code #{result}."
- end
+ end
end
def xml_rpc_destroy
diff --git a/app/models/settings.rb b/app/models/settings.rb
new file mode 100644
index 000000000..f6af89076
--- /dev/null
+++ b/app/models/settings.rb
@@ -0,0 +1,5 @@
+module Settings
+ def self.table_name_prefix
+ 'settings_'
+ end
+end
diff --git a/app/models/settings/notifier.rb b/app/models/settings/notifier.rb
new file mode 100644
index 000000000..af21fd811
--- /dev/null
+++ b/app/models/settings/notifier.rb
@@ -0,0 +1,5 @@
+class Settings::Notifier < ActiveRecord::Base
+ belongs_to :user
+
+ validates :user_id, :presence => true
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index affe00818..ae724821f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,9 +1,13 @@
class User < ActiveRecord::Base
ROLES = ['admin']
+ LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']]
+ LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last)
devise :database_authenticatable, :registerable, :omniauthable, # :token_authenticatable, :encryptable, :timeoutable
:recoverable, :rememberable, :validatable #, :trackable, :confirmable, :lockable
+ has_one :notifier, :class_name => 'Settings::Notifier' #:notifier
+
has_many :authentications, :dependent => :destroy
has_many :build_lists, :dependent => :destroy
@@ -26,11 +30,15 @@ class User < ActiveRecord::Base
validate { errors.add(:uname, :taken) if Group.where('uname LIKE ?', uname).present? }
validates :ssh_key, :uniqueness => true, :allow_blank => true
validates :role, :inclusion => {:in => ROLES}, :allow_blank => true
+ validates :language, :inclusion => {:in => LANGUAGES}, :allow_blank => true
- attr_accessible :email, :password, :password_confirmation, :remember_me, :login, :name, :ssh_key, :uname
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :login, :name, :ssh_key, :uname, :language
attr_readonly :uname, :own_projects_count
+ attr_readonly :uname
attr_accessor :login
+ after_create :create_settings_notifier
+
def admin?
role == 'admin'
end
@@ -75,5 +83,11 @@ class User < ActiveRecord::Base
clean_up_passwords
result
end
+
+ private
+
+ def create_settings_notifier
+ self.create_notifier
+ end
end
diff --git a/app/views/build_lists/show.html.haml b/app/views/build_lists/show.html.haml
index 9c7e779c5..1cd64f1e8 100644
--- a/app/views/build_lists/show.html.haml
+++ b/app/views/build_lists/show.html.haml
@@ -21,7 +21,9 @@
%b
= t("activerecord.attributes.build_list.container_path")
\:
- - if @build_list.container_path.present?
+ - if @build_list.status == BuildList::BUILD_PUBLISHED
+ = t("layout.build_lists.container_published")
+ - elsif @build_list.container_path.present?
- container_url = "http://#{request.host_with_port}/downloads#{@build_list.container_path}"
= link_to container_url, container_url
%p
diff --git a/app/views/comments/_form.html.haml b/app/views/comments/_form.html.haml
index 4078f495e..3600e8d2b 100644
--- a/app/views/comments/_form.html.haml
+++ b/app/views/comments/_form.html.haml
@@ -7,4 +7,4 @@
= image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
= t("layout.save")
%span.text_button_padding= t("layout.or")
- = link_to t("layout.cancel"), [@issue.project, @issue], :class => "text_button_padding link_button"
+ = link_to t("layout.cancel"), @commentable_path , :class => "text_button_padding link_button"
diff --git a/app/views/comments/_list.html.haml b/app/views/comments/_list.html.haml
new file mode 100644
index 000000000..25e6e13ee
--- /dev/null
+++ b/app/views/comments/_list.html.haml
@@ -0,0 +1,33 @@
+%a{ :name => "comments" }
+.block#block-list
+ .content
+ %h2.title
+ = t("layout.issues.comments_header")
+ .inner
+ %ul.list
+ - list.each do |comment|
+ %li
+ .left
+ = link_to comment.user.uname, user_path(comment.user.uname)
+ .item
+ = comment.body
+ %br
+ %br
+ - if commentable.class == Issue
+ - edit_path = edit_project_issue_comment_path(project, commentable, comment)
+ - delete_path = project_issue_comment_path(project, commentable, comment)
+ - elsif commentable.class == Grit::Commit
+ - edit_path = edit_project_commit_comment_path(project, commentable, comment)
+ - delete_path = project_commit_comment_path(project, commentable, comment)
+ = link_to t("layout.edit"), edit_path if can? :update, comment
+ = link_to image_tag("web-app-theme/icons/cross.png", :alt => t("layout.delete")) + " " + t("layout.delete"), delete_path, :method => "delete", :class => "button", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
+
+.block
+ .content
+ %h2.title
+ = t("layout.comments.new_header")
+ .inner
+ - new_path = project_issue_comments_path(project, commentable) if commentable.class == Issue
+ - new_path = project_commit_comments_path(project, commentable) if commentable.class == Grit::Commit
+ = form_for :comment, :url => new_path, :method => :post, :html => { :class => :form } do |f|
+ = render :partial => "comments/form", :locals => {:f => f}
diff --git a/app/views/comments/edit.html.haml b/app/views/comments/edit.html.haml
index 516ddd476..eb586af80 100644
--- a/app/views/comments/edit.html.haml
+++ b/app/views/comments/edit.html.haml
@@ -1,10 +1,10 @@
.block
.secondary-navigation
%ul.wat-cf
- %li.first= link_to t("layout.issues.list"), project_issue_path(@project, @issue)
+ %li.first= link_to t(@comment.commentable_type == 'Grit::Commit' ? "layout.git.repositories.commits" : "layout.issues.list"), @commentable_path
.content
%h2.title
- = t("layout.issues.edit_header")
+ = t("layout.#{@comment.commentable_type == 'Grit::Commit' ? 'comments' : 'issues'}.edit_header")
.inner
- = form_for @comment, :url => project_issue_comment_path(@project, @issue, @comment), :html => { :class => :form } do |f|
+ = form_for @comment, :url => @update_url, :html => { :class => :form } do |f|
= render :partial => "form", :locals => {:f => f}
diff --git a/app/views/devise/registrations/edit.html.haml b/app/views/devise/registrations/edit.html.haml
index 75d6fcfa0..b983f1836 100644
--- a/app/views/devise/registrations/edit.html.haml
+++ b/app/views/devise/registrations/edit.html.haml
@@ -39,6 +39,12 @@
- else
= resource.role
+ .group.wat-cf
+ .left
+ = f.label :language, :class => "label"
+ .right
+ = f.select :language, User::LANGUAGES_FOR_SELECT
+
/ .group.wat-cf
/ .left
/ = f.label :current_password, :class => "label"
@@ -68,3 +74,5 @@
%span.text_button_padding
= link_to t('layout.back'), :back, :class => "text_button_padding link_button"
+ .group.navform.wat-cf
+ = link_to t('layout.settings.notifier'), user_settings_notifier_path(current_user)#, :class => "text_button_padding link_button"
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index aeddc6958..5c9d0de5d 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -37,6 +37,12 @@
.right
= f.password_field :password_confirmation, :class => "text_field"
+ .group.wat-cf
+ .left
+ = f.label :language, :class => "label"
+ .right
+ = f.select :language, User::LANGUAGES_FOR_SELECT
+
.group.navform.wat-cf
%button.button{ :type => "submit" }
#{image_tag("web-app-theme/icons/tick.png", :alt => t("devise.registrations.sign_up_header"))} #{t("devise.registrations.sign_up_header")}
diff --git a/app/views/devise/shared/_links.haml b/app/views/devise/shared/_links.haml
index f3c6883ac..958f5ec3c 100644
--- a/app/views/devise/shared/_links.haml
+++ b/app/views/devise/shared/_links.haml
@@ -1,13 +1,13 @@
- if controller_name != 'sessions'
- = link_to "Войти", new_session_path(resource_name), :class => "text_button_padding link_button"
+ = link_to t("layout.devise.shared_links.sign_in"), new_session_path(resource_name), :class => "text_button_padding link_button"
- if devise_mapping.registerable? && controller_name != 'registrations'
- = link_to "Зарегистрироваться", new_registration_path(resource_name), :class => "text_button_padding link_button"
+ = link_to t("layout.devise.shared_links.sign_up"), new_registration_path(resource_name), :class => "text_button_padding link_button"
- if devise_mapping.recoverable? && controller_name != 'passwords'
- = link_to "Забыли пароль?", new_password_path(resource_name), :class => "text_button_padding link_button"
+ = link_to t("layout.devise.shared_links.forgot_password"), new_password_path(resource_name), :class => "text_button_padding link_button"
- if devise_mapping.confirmable? && controller_name != 'confirmations'
- = link_to "Не получили инструкции по подтверждению?", new_confirmation_path(resource_name), :class => "text_button_padding link_button"
+ = link_to t("layout.devise.shared_links.confirm_again"), new_confirmation_path(resource_name), :class => "text_button_padding link_button"
- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
- = link_to "Не получили инструкции по разблокировке?", new_unlock_path(resource_name), :class => "text_button_padding link_button"
+ = link_to t("layout.devise.shared_links.unlock"), new_unlock_path(resource_name), :class => "text_button_padding link_button"
- if devise_mapping.omniauthable?
- resource_class.omniauth_providers.each do |provider|
- = link_to "Войти через #{provider.to_s.classify}", omniauth_authorize_path(resource_name, provider), :class => "text_button_padding link_button"
\ No newline at end of file
+ = link_to t("layout.devise.shared_links.sign_in_through", :provider => provider.to_s.classify), omniauth_authorize_path(resource_name, provider), :class => "text_button_padding link_button"
diff --git a/app/views/git/blobs/show.html.haml b/app/views/git/blobs/show.html.haml
index 2059f0a03..04b3a19b3 100644
--- a/app/views/git/blobs/show.html.haml
+++ b/app/views/git/blobs/show.html.haml
@@ -13,6 +13,7 @@
.content
.inner
%h3= render_path
+ %h3= @blob.mime_type
.blob_header
.size #{(@blob.size / 1024.0).round(3)} Kb
@@ -22,13 +23,33 @@
- else
#{link_to "Raw", raw_path(@project, @treeish, @path)} #{link_to "Blame", blame_path(@project, @treeish, @path)} #{link_to "History", commits_path(@project, @treeish, @path)}
.clear
- %table.table.blob
- %tr
- %td.lines
- :plain
- #{render_line_numbers(@blob.data.split("\n").length)}
- %td.blob
- :plain
- #{render_blob(@blob)}
+ - case choose_render_way(@blob)
+ - when :image
+ %table.table.blob
+ %tr
+ %td.lines
+ %td.blob
+ :plain
+
+
+
+ - when :text
+ %table.table.blob
+ %tr
+ %td.lines
+ :plain
+ #{render_line_numbers(@blob.data.split("\n").length)}
+ %td.blob
+ :plain
+ #{render_blob(@blob)}
+ - when :binary
+ %table.table.blob
+ %tr
+ %td.lines
+ %td.blob
+ :plain
+
+ #{ link_to @blob.basename, raw_path(@project, @treeish, @path) }
+
-- content_for :sidebar, render(:partial => 'git/shared/sidebar')
\ No newline at end of file
+- content_for :sidebar, render(:partial => 'git/shared/sidebar')
diff --git a/app/views/git/commits/show.html.haml b/app/views/git/commits/show.html.haml
index e5d39833e..8f3ec67f8 100644
--- a/app/views/git/commits/show.html.haml
+++ b/app/views/git/commits/show.html.haml
@@ -26,3 +26,5 @@
%p= t 'layout.git.repositories.commit_diff_too_big'
- content_for :sidebar, render(:partial => 'git/shared/sidebar')
+
+= render :partial => "comments/list", :locals => {:list => Project.commit_comments(@commit, @project), :project => @project, :commentable => @commit}
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index ea6a25a13..9f1c6306d 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -19,4 +19,4 @@
= render :partial => 'issues/list'
.actions-bar.wat-cf
.actions
- = will_paginate @issues, :param_name => :issue_page
+ = will_paginate @issues#, :param_name => :issue_page
diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml
index 49b229b5c..a8d1c3e6e 100644
--- a/app/views/issues/show.html.haml
+++ b/app/views/issues/show.html.haml
@@ -29,28 +29,4 @@
- else
= link_to t('layout.issues.subscribe_btn'), project_issue_subscribes_path(@project, @issue), :method => :post
-%a{ :name => "comments" }
-.block#block-list
- .content
- %h2.title
- = t("layout.issues.comments_header")
- .inner
- %ul.list
- - @issue.comments.each do |comment|
- %li
- .left
- = link_to comment.user.uname, user_path(comment.user.uname)
- .item
- = comment.body
- %br
- %br
- = link_to t("layout.edit"), edit_project_issue_comment_path(@project, @issue.id, comment) if can? :update, comment
- = link_to image_tag("web-app-theme/icons/cross.png", :alt => t("layout.delete")) + " " + t("layout.delete"), project_issue_comment_path(@project, @issue.id, comment), :method => "delete", :class => "button", :confirm => t("layout.comments.confirm_delete") if can? :delete, comment
-
-.block
- .content
- %h2.title
- = t("layout.comments.new_header")
- .inner
- = form_for :comment, :url => project_issue_comments_path(@project, @issue), :method => :post, :html => { :class => :form } do |f|
- = render :partial => "comments/form", :locals => {:f => f}
+= render :partial => "comments/list", :locals => {:list => @issue.comments.order(:created_at), :project => @project, :commentable => @issue}
diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml
index 2fc1915cc..0f318764e 100644
--- a/app/views/projects/_form.html.haml
+++ b/app/views/projects/_form.html.haml
@@ -16,6 +16,9 @@
.group
= f.label :has_wiki, t("activerecord.attributes.project.has_wiki"), :class => :label
= f.check_box :has_wiki
+.group
+ = f.label :srpm, t("activerecord.attributes.project.srpm"), :class => :label
+ = f.file_field :srpm, :class => 'file_field'
.group.navform.wat-cf
%button.button{:type => "submit"}
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index ba3c5c14f..1017c5329 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -8,7 +8,7 @@
.content
%h2.title= t("layout.projects.edit_header")
.inner
- = form_for @project, :html => { :class => :form } do |f|
+ = form_for @project, :html => { :class => :form, :multipart => true } do |f|
= render :partial => "form", :locals => {:f => f}
- content_for :sidebar, render('sidebar')
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index f9304bdd8..6e5ec7973 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -9,7 +9,7 @@
.content
%h2.title= t("layout.projects.new_header")
.inner
- = form_for [get_owner, @project], :html => { :class => :form } do |f|
+ = form_for [get_owner, @project], :html => { :class => :form, :multipart => true } do |f|
= render :partial => "form", :locals => {:f => f}
-# content_for :sidebar, render('sidebar')
diff --git a/app/views/settings/notifiers/_form.html.haml b/app/views/settings/notifiers/_form.html.haml
new file mode 100644
index 000000000..2631874bc
--- /dev/null
+++ b/app/views/settings/notifiers/_form.html.haml
@@ -0,0 +1,29 @@
+.group
+ = f.label :can_notify, t('activerecord.attributes.settings.notifier.can_notify'), :class => :label
+ = f.check_box :can_notify#, :class => 'text_field'
+
+.group
+ = f.label :new_comment, t('activerecord.attributes.settings.notifier.new_comment'), :class => :label
+ = f.check_box :new_comment, :class => 'notify_cbx'
+
+.group
+ = f.label :new_comment_reply, t('activerecord.attributes.settings.notifier.new_comment_reply'), :class => :label
+ = f.check_box :new_comment_reply, :class => 'notify_cbx'
+
+.group
+ = f.label :new_issue, t('activerecord.attributes.settings.notifier.new_issue'), :class => :label
+ = f.check_box :new_issue, :class => 'notify_cbx'
+
+.group
+ = f.label :issue_assign, t('activerecord.attributes.settings.notifier.issue_assign'), :class => :label
+ = f.check_box :issue_assign, :class => 'notify_cbx'
+
+.group.navform.wat-cf
+ %button.button{:type => "submit"}
+ = image_tag("web-app-theme/icons/tick.png", :alt => t("layout.save"))
+ = t("layout.save")
+ %span.text_button_padding= t("layout.or")
+ = link_to t("layout.cancel"), user_settings_notifier_path(@user), :class => "text_button_padding link_button"
+
+:javascript
+ disableNotifierCbx($('#settings_notifier_can_notify'));
diff --git a/app/views/settings/notifiers/show.html.haml b/app/views/settings/notifiers/show.html.haml
new file mode 100644
index 000000000..97f82b931
--- /dev/null
+++ b/app/views/settings/notifiers/show.html.haml
@@ -0,0 +1,5 @@
+#block-signup.block
+ %h2= title t("layout.settings.notifiers.edit_header")
+ .content
+ = form_for @notifier, :url => user_settings_notifier_path(@user), :html => { :class => :form } do |f|
+ = render :partial => "form", :locals => {:f => f}
diff --git a/app/views/user_mailer/issue_assign_notification.en.haml b/app/views/user_mailer/issue_assign_notification.en.haml
new file mode 100644
index 000000000..83c33e8ac
--- /dev/null
+++ b/app/views/user_mailer/issue_assign_notification.en.haml
@@ -0,0 +1,7 @@
+%p== Hello, #{@user.name}.
+
+
+%p You have been assigned to issue #{ link_to @issue.title, [@issue.project, @issue] }
+
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/issue_assign_notification.haml b/app/views/user_mailer/issue_assign_notification.ru.haml
similarity index 100%
rename from app/views/user_mailer/issue_assign_notification.haml
rename to app/views/user_mailer/issue_assign_notification.ru.haml
diff --git a/app/views/user_mailer/new_comment_notification.en.haml b/app/views/user_mailer/new_comment_notification.en.haml
new file mode 100644
index 000000000..7c02852bc
--- /dev/null
+++ b/app/views/user_mailer/new_comment_notification.en.haml
@@ -0,0 +1,9 @@
+%p== Hello, #{@user.name}.
+
+
+%p To the issue #{ link_to @comment.commentable.title, [@comment.commentable.project, @comment.commentable] } added a comment.
+
+%p "#{ @comment.body }"
+
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/new_comment_notification.haml b/app/views/user_mailer/new_comment_notification.ru.haml
similarity index 91%
rename from app/views/user_mailer/new_comment_notification.haml
rename to app/views/user_mailer/new_comment_notification.ru.haml
index 88692f64e..315a56b88 100644
--- a/app/views/user_mailer/new_comment_notification.haml
+++ b/app/views/user_mailer/new_comment_notification.ru.haml
@@ -3,5 +3,7 @@
%p К задаче #{ link_to @comment.commentable.title, [@comment.commentable.project, @comment.commentable] } был добавлен новый комментарий.
+%p "#{ @comment.body }"
+
%p== Команда поддержки «ROSA Build System»
diff --git a/app/views/user_mailer/new_comment_reply_notification.en.haml b/app/views/user_mailer/new_comment_reply_notification.en.haml
new file mode 100644
index 000000000..9324062f2
--- /dev/null
+++ b/app/views/user_mailer/new_comment_reply_notification.en.haml
@@ -0,0 +1,9 @@
+%p== Hello, #{@user.name}.
+
+
+%p Your comment into issue #{ link_to @comment.commentable.title, [@comment.commentable.project, @comment.commentable] } has been answered.
+
+%p "#{ @comment.body }"
+
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/new_comment_reply_notification.ru.haml b/app/views/user_mailer/new_comment_reply_notification.ru.haml
new file mode 100644
index 000000000..48ff0ab4b
--- /dev/null
+++ b/app/views/user_mailer/new_comment_reply_notification.ru.haml
@@ -0,0 +1,9 @@
+%p== Здравствуйте, #{@user.name}.
+
+
+%p На Ваш комментарий в задаче #{ link_to @comment.commentable.title, [@comment.commentable.project, @comment.commentable] } был дан ответ.
+
+%p "#{ @comment.body }"
+
+
+%p== Команда поддержки «ROSA Build System»
diff --git a/app/views/user_mailer/new_issue_notification.en.haml b/app/views/user_mailer/new_issue_notification.en.haml
new file mode 100644
index 000000000..f814fa617
--- /dev/null
+++ b/app/views/user_mailer/new_issue_notification.en.haml
@@ -0,0 +1,7 @@
+%p== Hello, #{@user.name}.
+
+
+%p To project #{ link_to @issue.project.name, project_path(@issue.project) } has been added an issue #{ link_to @issue.title, [@issue.project, @issue] }
+
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/new_issue_notification.haml b/app/views/user_mailer/new_issue_notification.ru.haml
similarity index 100%
rename from app/views/user_mailer/new_issue_notification.haml
rename to app/views/user_mailer/new_issue_notification.ru.haml
diff --git a/app/views/user_mailer/new_user_notification.en.haml b/app/views/user_mailer/new_user_notification.en.haml
new file mode 100644
index 000000000..d1a0722bf
--- /dev/null
+++ b/app/views/user_mailer/new_user_notification.en.haml
@@ -0,0 +1,12 @@
+%p== Hello, #{@user.name}.
+
+
+%p You have been sign up to project «ROSA Build System» and now can sign in.
+
+
+%p
+ ==Your email : #{@user.email}
+ %br/
+ ==Your password: #{@user.password}
+
+%p== Support team «ROSA Build System»
diff --git a/app/views/user_mailer/new_user_notification.haml b/app/views/user_mailer/new_user_notification.ru.haml
similarity index 100%
rename from app/views/user_mailer/new_user_notification.haml
rename to app/views/user_mailer/new_user_notification.ru.haml
diff --git a/bin/import_srpm.sh b/bin/import_srpm.sh
new file mode 100755
index 000000000..6b3bd1512
--- /dev/null
+++ b/bin/import_srpm.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+# import_srpm.sh: Import SRPM packages to git repo
+
+# Input data
+srpm_path=$1
+git_path=$2
+git_branch=$3
+name=$(rpm -q --qf '[%{Name}]' -p $srpm_path)
+version=$(rpm -q --qf '[%{Version}]' -p $srpm_path)
+tmp_dir=/tmp/$name-$version-$RANDOM
+
+# Clone destination repo
+mkdir -p $tmp_dir
+git clone $git_path $tmp_dir
+
+# Switch to import branch
+cd $tmp_dir
+git branch --track $git_branch origin/$git_branch # Try track remote
+git branch $git_branch # Try create local
+git checkout $git_branch
+
+# Remove all files except .git
+rm -rf $tmp_dir/*
+mv $tmp_dir/.git $tmp_dir/git
+rm -rf $tmp_dir/.*
+mv $tmp_dir/git $tmp_dir/.git
+
+# Unpack srpm
+rpm2cpio $srpm_path > srpm.cpio
+cpio -idv < srpm.cpio
+rm -f srpm.cpio
+
+# Commit and push changes
+git add -A .
+git commit -m "Automatic import for version $version"
+git push origin HEAD
+
+# Cleanup
+rm -rf $tmp_dir
diff --git a/bin/mount_downloads.sh b/bin/mount_downloads.sh
index 6bb68f669..11c2f45ca 100755
--- a/bin/mount_downloads.sh
+++ b/bin/mount_downloads.sh
@@ -2,9 +2,20 @@
for f in `ls /srv/rosa_build/shared/downloads`
do
- if [ -d /home/share/platforms/$f ]
- then
- sudo umount /srv/rosa_build/shared/downloads/$f 2>&1 >> /dev/null
- sudo mount --bind /home/share/platforms/$f /srv/rosa_build/shared/downloads/$f
- fi
+ if [ -d /home/share ]
+ then
+ # Staging case
+ if [ -d /home/share/platforms/$f ]
+ then
+ sudo umount /srv/rosa_build/shared/downloads/$f 2>&1 >> /dev/null
+ sudo mount --bind /home/share/platforms/$f /srv/rosa_build/shared/downloads/$f
+ fi
+ else
+ # Production case
+ if [ -d /share/platforms/$f ]
+ then
+ sudo umount /srv/rosa_build/shared/downloads/$f 2>&1 >> /dev/null
+ sudo mount --bind /share/platforms/$f /srv/rosa_build/shared/downloads/$f
+ fi
+ fi
done
diff --git a/config/application.rb b/config/application.rb
index 090e206c5..901d86784 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -32,7 +32,7 @@ module Rosa
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
- config.i18n.default_locale = :ru
+ config.i18n.default_locale = :en
config.action_view.javascript_expansions[:defaults] = %w()
diff --git a/config/deploy.rb b/config/deploy.rb
index d8234e321..b03d867e4 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -1,15 +1,17 @@
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
set :rvm_type, :user
+
require 'rvm/capistrano'
require 'bundler/capistrano'
require 'delayed/recipes'
require 'airbrake/capistrano'
+
set :whenever_command, "bundle exec whenever"
# require "whenever/capistrano"
-set :default_stage, "staging"
-# set :stages, %w(production staging pingwinsoft ui) # auto readed
require 'capistrano/ext/multistage'
+set :default_stage, "staging"
+# set :stages, %w(production staging pingwinsoft) # auto readed
# main details
ssh_options[:forward_agent] = true
@@ -21,20 +23,15 @@ set :user, "rosa"
set :use_sudo, false
set :keep_releases, 3
+set :scm, :git
set :repository, "git@github.com:warpc/rosa-build.git"
-# set :git_shallow_clone, 1
-set :scm, "git"
-# set :deploy_via, :copy
-# set :copy_cache, true
+set :deploy_via, :remote_cache
require 'lib/recipes/nginx'
require 'lib/recipes/unicorn'
require 'lib/recipes/bluepill'
-namespace :deploy do
- # task :restart, :roles => :app, :except => { :no_release => true } do
- # run "touch #{current_release}/tmp/restart.txt"
- # end
+namespace :deploy do
task :stub_xml_rpc do
path = File.join(release_path, 'config', 'environment.rb')
code = %Q{\nrequire 'stub_xml_rpc'\n}
@@ -42,25 +39,34 @@ namespace :deploy do
run %Q{echo "#{code}" >> #{path}}
end
- task :symlink_all, :roles => :web do
+ task :symlink_all, :roles => :app do
run "mkdir -p #{fetch :shared_path}/config"
+
+ # Setup DB
run "cp -n #{fetch :release_path}/config/database.yml.sample #{fetch :shared_path}/config/database.yml"
- run "cp -n #{fetch :release_path}/config/application.yml.sample #{fetch :shared_path}/config/application.yml"
run "ln -nfs #{fetch :shared_path}/config/database.yml #{fetch :release_path}/config/database.yml"
+
+ # Setup application
+ run "cp -n #{fetch :release_path}/config/deploy/application.#{fetch :stage}.yml #{fetch :shared_path}/config/application.yml"
run "ln -nfs #{fetch :shared_path}/config/application.yml #{fetch :release_path}/config/application.yml"
+ # It will survive downloads folder between deployments
run "mkdir -p #{fetch :shared_path}/downloads"
run "ln -nfs #{fetch :shared_path}/downloads/ #{fetch :release_path}/public/downloads"
end
+
+ task :symlink_pids, :roles => :app do
+ run "cd #{fetch :shared_path}/tmp && ln -nfs ../pids pids"
+ end
end
after "deploy:update_code", "deploy:symlink_all", "deploy:migrate"
-after "deploy:restart", "delayed_job:restart", "bluepill:restart", "deploy:cleanup"
+after "deploy:restart","bluepill:stop", "delayed_job:restart", "deploy:cleanup", "bluepill:start"
+after "deploy:setup", "deploy:symlink_pids"
require 'cape'
namespace :rake_tasks do
Cape do
- # mirror_rake_tasks
mirror_rake_tasks 'db:seeds'
end
end
diff --git a/config/deploy/application.production.yml b/config/deploy/application.production.yml
new file mode 100644
index 000000000..450faf330
--- /dev/null
+++ b/config/deploy/application.production.yml
@@ -0,0 +1,15 @@
+production:
+ root_path: /share
+ nginx_log: /srv/rosa_build/shared/log/nginx.access.log
+ do-not-reply-email: do-not-reply@rosalab.ru
+ project_name: ABF
+ repo_project_name: ABF
+ build_server_ip: 127.0.0.1
+ build_server_port: 12555
+ build_server_path: /xmlrpc
+ product_builder_ip:
+ mdv: 192.168.122.19
+ nau5: 192.168.122.203
+ product_builder_port: 12554
+ product_builder_path: /xmlrpc
+ distr_types: ['mdv']
\ No newline at end of file
diff --git a/config/deploy/application.staging.yml b/config/deploy/application.staging.yml
new file mode 100644
index 000000000..6e9ae1cac
--- /dev/null
+++ b/config/deploy/application.staging.yml
@@ -0,0 +1,15 @@
+production:
+ root_path: /share
+ nginx_log: /srv/rosa_build/shared/log/nginx.access.log
+ do-not-reply-email: do-not-reply@rosalab.ru
+ project_name: ABF
+ repo_project_name: ABF
+ build_server_ip: 127.0.0.1
+ build_server_port: 12555
+ build_server_path: /xmlrpc
+ product_builder_ip:
+ mdv: 192.168.122.19
+ nau5: 192.168.122.203
+ product_builder_port: 12554
+ product_builder_path: /xmlrpc
+ distr_types: ['mdv', 'nau5']
diff --git a/config/deploy/ui.rb b/config/deploy/ui.rb
deleted file mode 100644
index 824b9075b..000000000
--- a/config/deploy/ui.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-set :branch, "ui"
-
-set :domain, "abf.warpc.ru" # "195.19.76.12"
-set :port, 1822
-
-role :app, domain
-role :web, domain
-role :db, domain, :primary => true
-
-set :application, "rosa_build_#{stage}"
-set :deploy_to, "/srv/#{application}"
-
-# set :unicorn_port, 8082
-
-before "deploy:restart", "deploy:stub_xml_rpc"
diff --git a/config/environments/production.rb b/config/environments/production.rb
index f29b78fce..0d9247b3a 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -36,7 +36,7 @@ Rosa::Application.configure do
# Disable delivery errors, bad email addresses will be ignored
# config.action_mailer.raise_delivery_errors = false
- config.action_mailer.default_url_options = { :host => 'npp-build.rosalab.ru' }
+ config.action_mailer.default_url_options = { :host => 'rosa-build.rosalab.ru' }
# Enable threaded mode
# config.threadsafe!
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 5e4e43321..7f0e522af 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -20,6 +20,8 @@ en:
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
updated: 'Your password was changed successfully. You are now signed in.'
+ button: 'Submit'
+ edit_button: 'Change my password'
confirmations:
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
confirmed: 'Your account was successfully confirmed. You are now signed in.'
@@ -27,6 +29,11 @@ en:
signed_up: 'You have signed up successfully. If enabled, a confirmation was sent to your e-mail.'
updated: 'You updated your account successfully.'
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
+ sign_up_header: 'Signup'
+ edit_password_description: Leave blank if you don't want to change it
+ current_password_description: 'We need your current password to confirm your changes'
+ cancel: 'Cancel my account'
+ cancel_confirmation: 'Are you sure?'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account was successfully unlocked. You are now signed in.'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index a747bfa69..0708026ca 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,5 +1,705 @@
-# Sample localization file for English. Add more files in this directory for other locales.
-# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
-
en:
- hello: "Hello world"
+ will_paginate:
+ previous_label: ‹ Previous
+ next_label: Next ›
+ page_gap: ...
+
+ datatables:
+ previous_label: ‹ Prev.
+ next_label: Next ›b r
+ first_label: « First
+ last_label: Last »
+ empty_label: No data accessible
+ info_label: Records displayed from _START_ to _END_ total _TOTAL_
+ info_empty_label: Records displayed from 0 to 0 total 0
+ filtered_label: (filtered of _MAX_)
+
+ layout:
+ logged_in_as: You logged as
+ logout: Logout
+ user_list: User list
+ edit: Edit
+ show: View
+ cancel: Cancel
+ create: Create
+ delete: Erase
+ save: Save
+ search: Search
+ clone: Clone
+ search_by_name: Filter by name
+ are_you_sure: "Sure?"
+ login: Login
+ or: or
+ yes_: Yes
+ no_: No
+ true_: True
+ false_: False
+ publish: Publish
+ add: Add
+ upload: Upload
+ not_access: Access denied!
+ owner: Owner
+ confirm: Sure?
+ back: Back
+ settings:
+ notifier: Notifier setting
+ notifiers:
+ edit_header: Notifier setting
+ processing: working ...
+ invalid_content_type: incorrect type
+
+ devise:
+ shared_links:
+ sign_in: Sign in
+ sign_up: Sign up
+ forgot_password: Forgot your password?
+ confirm_again: Do not receive the confirmation link?
+ unlock: Do not receive unlock instructions?
+ sign_in_through: Sign in by %{provider}
+
+ downloads:
+ title: Downloads statistic
+ message: Automatically updated every 5 minutes
+ refresh_btn: Refresh
+
+ auto_build_lists:
+ header: Automated build projects
+ message: All projects build under user repository and architecture i586
+ project: Project
+ action: Action
+ automate_btn: Automate
+ cancel_btn: Cancel
+ not_automated: Not automated
+ already_automated: Automated
+
+ weekdays:
+ Monday: Monday
+ Tuesday: Tuesday
+ Wednesday: Wednesday
+ Thursday: Thursday
+ Friday: Friday
+ Saturday: Saturday
+ Sunday: Sunday
+
+ menu:
+ categories: Catalogue
+ containers: Containers
+ downloads: Statistics
+ event_logs: Event log
+ build_lists: Task monitoring
+ groups: Groups
+ platforms: Platforms
+ products: Products
+ projects: Projects
+ repositories: Repositories
+ rights: Rights
+ roles: Roles
+ users: Users
+ personal_repository: My repository
+ auto_build_lists: Automated build
+
+ sessions:
+ sign_in_header: Sign in
+
+ private_users:
+ list: List
+ new: New pair
+ list_header: Pair login/password
+ confirm_delete: Are you sure to delete this pair login/password?
+ confirm_regenerate: Are you sure to regenerate this pair login/password?
+ regenerate_btn: Regenerate
+ warning_message: Warning - Old data set as invalid when new data obtaining
+
+ categories:
+ list: List
+ new: Create
+ edit: Edit
+ platforms: By platform
+ list_header: Catalogue
+ new_header: New category
+ edit_header: Edit category
+ confirm_delete: Are you sure to delete this category?
+
+ issues:
+ list: List
+ edit: Edit
+ comments_header: Comments
+ new: New task
+ list_header: List
+ confirm_delete: Are you sure to delete this task?
+ edit_header: Task edit
+ new_header: New task
+ statuses:
+ open: Opened
+ closed: Closed
+ any: Any
+ subscribe: Subscribe
+ subscribe_btn: Subscribe
+ unsubscribe_btn: Unsubscribe
+
+ comments:
+ confirm_delete: Are you sure to delete the comment?
+ new_header: New comment
+ edit_header: Editing a comment
+
+ platforms:
+ admin_id: Owner
+ build_all: Build all
+ list: List
+ new: Create
+ edit: Edit
+ new_header: New platform
+ edit_header: Edit
+ list_header: Platforms
+ list_header_main: General
+ list_header_personal: Personal
+ list_header_all: All
+ clone_header: Platform clone
+ show: Platform
+ projects: Projects
+ products: Products
+ location: Location
+ repositories: Repositories
+ back_to_the_list: ⇐To platform list
+ freeze: Freeze
+ unfreeze: Unfeeze
+ confirm_freeze: Are you sure to freeze this platform?
+ confirm_freeze: Are you sure to clone this platform?
+ confirm_unfreeze: Are you sure to defrost this platform?
+ released_suffix: (released)
+ confirm_delete: Are you sure to delete this platform?
+ current_platform_header: Current platform
+ owner: Owner
+ visibility: Visibility
+ platform_type: Platform type
+ distrib_type: Distribution kit type
+ private_users: Access data
+ confirm_clone: To clone?
+ clone: To clone
+
+ event_logs:
+ list:List
+ list_header: Event log
+
+ repositories:
+ list: List
+ list_header: Repositories
+ new: New repository
+ new_header: New repository
+ show: Repository
+ location: Location
+ projects: Projects
+ new_header: New repository
+ back_to_the_list: ⇐ List of repositories
+ confirm_delete: Are you sure to delete this repository?
+ current_repository_header: Current repository
+
+ personal_repositories:
+ settings_header: Settings
+ change_visibility_from_hidden: Replace the status to "Opened"
+ change_visibility_from_open: Replace the status to "Private"
+ settings: Settings
+ show: My repository
+ private_users: Private repository users
+
+ products:
+ list: List
+ new: New product
+ list_header: Products
+ clone: Clone
+ build: Build
+ new_header: New product
+ edit_header: Product editing
+ confirm_delete: Are you sure to delete this product?
+
+ cron_tab_generator:
+ show: Show cron tab the generator
+ hide: Hide cron tab the generator
+ choose: Choose
+ every_minute: Every minute
+ every_hour: Every hour
+ every_day: Every day
+ every_month: Every month
+ every_weekday: Every weekdays
+ minutes: Minutes
+ hours: Hours
+ days: Days
+ months: Months
+ weekdays: weekdays
+
+ projects:
+ add: Add
+ edit: Edit
+ list: List
+ list_header: Projects
+ edit_header: Edit the project
+ show: Project
+ build: Build
+ new_build: New build %{project_name}
+ confirm_delete: Are you sure to delete this project?
+ new: New project
+ new_header: New project
+ new_header: New project
+ location: Location
+ git_repo_location: Path to git repo
+ current_project_header: Current project
+ current_build_lists: Current builds
+ build_button: Start build
+ add_collaborators: Add collaborators
+ members: Members
+ collaborators: Collaborators
+ groups: Groups
+ edit_collaborators: Edit collaborators
+ issues: Issues
+
+ collaborators:
+ back_to_proj: Back to project
+ edit: Edit list
+ add: Add/Remove
+ list: List
+ edit_roles: Edit roles
+ roles_header: Roles to
+ add_role: Add/Remove a role
+ input_username: Enter an username
+ input_groupname: Enter a groupname
+
+ members:
+ back_to_group: Back to group
+ edit: Edit list
+ roles: Roles
+ add_member: Add member
+ input_username: Username
+
+ groups:
+ list: List
+ new: Create
+ edit: Edit
+ members: Members
+ new_header: New group
+ edit_header: Edit
+ list_header: Groups
+ show: Group
+ back_to_the_list: ⇐ List of groups
+ confirm_delete: Are you sure to remove this group?
+ edit_members: Edit members
+
+ users:
+ list: List
+ new: Create
+ edit: Edit
+ new_header: New user
+ edit_header: Edit
+ list_header: Users
+ groups: Groups
+ show: User
+ back_to_the_list: ⇐ List of users
+ confirm_delete: Are you sure to remove this user?
+ own_projects: My projects
+ part_projects: Participate projects
+ filter_header: Filter
+
+ git:
+ repositories:
+ empty: Empty repository
+ source: Source
+ commits: Commits
+ commit_diff_too_big: Sorry, commit too big!
+ tags: Tags
+ branches: Branches
+ project_versions: Versions
+
+ product_build_lists:
+ statuses:
+ '0': 'build'
+ '1': 'build error'
+ '2': 'build in progress'
+
+ build_lists:
+ filter_header: Filter
+ current: Curent
+ created_at_start: "Build start from:"
+ created_at_end: "Build start to:"
+ notified_at_start: "Last update time by BS from:"
+ notified_at_end: " Last update time by BS to:"
+ bs_id_search: 'Id search'
+ project_name_search: Project name search
+ bs_id_not_set: Id isn’t set
+ items_header: Build items
+ no_items_data: No data
+ show: Show
+ cancel_button_header: Action
+ cancel_button: Cancel
+ cancel_success: 'Build canceled'
+ cancel_fail: 'Errors on build cancelling!'
+ publish_success: 'Build on publish queue'
+ publish_fail: 'Errors on publish queue!'
+ container_published: 'Container in a repository'
+
+ build_server_status:
+ header: Build server status
+ client_count: Clients count
+ count_new_task: New task count
+ count_build_task: Build task count
+
+ items:
+ statuses:
+ build_started: Build started
+ build_error: Build error
+ dependencies_error: Dependences not found
+ success: Build complete
+ unknown: Build waiting
+ git_error: Git error
+
+ statuses:
+ build_error: Build error
+ build_published: Build published
+ build_publish: Build publishing
+ failed_publish: Publishing error
+ dependencies_fail: Dependences not found
+ waiting_for_response: Waiting for response
+ build_pending: Build pending
+ dependency_test_failed: Dependency test failed
+ binary_test_failed: Binary test failed
+ build_canceled: Build canceled
+ success: Build complete
+ build_started: Build started
+ platform_not_found: Platform not found
+ platform_pending: Platforn pending
+ project_not_found: Project not found
+ project_version_not_found: Project version not found
+
+ flash:
+ settings:
+ saved: Settings saved success
+ save_error: Setting update error
+
+
+ subscribe:
+ saved: Subscription on notifications for this task is created
+ destroyed: Subscription on notifications for this task is cleaned
+
+ exception_message: Access violation to this page!
+
+ downloads:
+ statistics_refreshed: Statistics refreshed
+
+ collaborators:
+ successfully_changed: Collaborators list successfully changed
+ error_in_changing: Collaborators list changing error
+ member_already_added: Member %s already added
+ group_already_added: Group already added
+ successfully_added: Member %s successfully added
+ error_in_adding: Member %s adding error
+
+ members:
+ successfully_changed: Members list successfully changed
+ error_in_changing: Members list changing error
+ successfully_added: Member successfully added
+ error_in_adding: Member adding error
+ already_added: User already added
+
+ auto_build_list:
+ success: Automated build success!
+ failed: Automated build failed!
+ cancel: Automated build canceled!
+ cancel_failed: Automated build canceling failed!
+
+ category:
+ saved: Category saved
+ save_error: Category saves error
+ destroyed: Category deleted
+
+ comment:
+ saved: Comment saved
+ save_error: Comment saves error
+ destroyed: Comment deleted
+
+ issue:
+ saved: Task saved
+ save_error: Task saves error
+ destroyed: Task deleted
+
+ project:
+ saved: Project saved
+ save_error: Project saves error
+ save_warning_ssh_key: Owner of the project must specify in profile a SSH key
+ destroyed: Project deleted
+ forked: Project forked
+ fork_error: Project fork error
+
+ user:
+ saved: User saved
+ save_error: User data saves error
+ destroyed: User account deleted
+
+ group:
+ saved: Group saved
+ save_error: Group saves error
+ destroyed: Group deleted
+ user_uname_exists: User already exists
+
+ repository:
+ saved: Repository added
+ save_error: Repository adding error
+ destroyed: Repository deleted
+ project_added: Project added on repository
+ project_not_added: Project adding error. In this repository already is a project with such name. First remove the old project
+ project_removed: Project deleted
+ project_not_removed: Project deleting failed
+
+ product:
+ saved: Product saved
+ save_error: Product saves error
+ build_started: Product build started
+ destroyed: Product deleted
+
+ platform:
+ saved: Platform saved
+ save_error: Platform saves error
+ freezed: Platform freezed
+ freeze_error: Platform freezing error, try again
+ unfreezed: Platform unfreezed
+ unfreeze_error: Platform unfreezing error, try again
+ destroyed: Platform deleted
+ build_all_success: All project build in progress
+
+ build_list:
+ saved: Project version '%{project_version}' build list, platform '%{bpl}', architecture '%{arch}' creation success
+ save_error: Project version '%{project_version}' build list, platform '%{bpl}', architecture '%{arch}' creation error
+ no_project_version_selected: Select any version of project
+ no_project_version_found: Project version '%{project_version}' not found
+ no_arch_or_platform_selected: At least one of architecture of platform must selected
+ wrong_platform: For the main repository its mail platform can be chosen only!
+ can_not_published: Build publishing with status "Build" available only
+
+ attributes:
+ password: Password
+ password_confirmation: Confirmation
+ remember_me: Remember
+ name: Name
+ parent_platform_id: Parent platform
+ build_list: Build list
+
+ activerecord:
+ models:
+ category: Category
+ repository: Repository
+ arch: Arch
+ container: Container
+ platform: Platform
+ group: Group
+ event_log: Event log
+ project: Project
+ rpm: RPM
+ user: User
+ private_user: Private user
+ product: Product
+ product_build_list: Product build list
+ build_list: Build list
+ build_list_item: Build list item
+ download: Statistics
+ auto_build_list: Auto rebuild list
+ settings:
+ notifier: Notifies setting
+
+ attributes:
+ settings:
+ notifier:
+ can_notify: Notifications by e-mail
+ new_comment: New task comment notifications
+ new_comment_reply: New reply of comment notifications
+ new_issue: New task notifications
+ issue_assign: New task assignment notifications
+
+ auto_build_list:
+ project_id: Project
+ project: Project
+ bpl_id: Repository for saving
+ bpl: Repository for saving
+ pl_id: Platform
+ pl: Platform
+ arch_id: Architecture
+ arch: Architecture
+
+ comment:
+ body: Content
+ user: Author
+
+ issue:
+ title: Title
+ body: Content
+ user: Assigned
+ user_id: Assigned
+ project: Project
+ status: Status
+
+ private_user:
+ login: Login
+ password: Password
+
+ category:
+ parent_id: Parent
+ name: Name
+
+ repository:
+ name: Name
+ description: Description
+ platform_id: Platform
+ platform: Platform
+ created_at: Created
+ updated_at: Updated
+ owner: Owner
+
+ product:
+ name: Name
+ platform_id: Platform
+ build_status: Build status
+ build_path: ISO path
+ created_at: Created
+ updated_at: Updated
+ ks: Content .ks.template
+ counter: Content .counter
+ build_script: Content build
+ menu: Content .menu.xml
+ tar: Tar.bz2 file
+ is_template: Template
+ system_wide: System
+ cron_tab: Cront tab
+ use_cron: Cron usage
+
+ arch:
+ name: Name
+ created_at: Created
+ updated_at: Updated
+
+ container:
+ name: Name
+ project_id: Project
+ project: Project
+ owner_id: Owner
+ owner: Owner
+ created_at: Created
+ updated_at: Updated
+
+ platform:
+ name: Name
+ description: Description
+ parent_platform_id: Parent platform
+ parent: Parent platform
+ released: Released
+ created_at: Created
+ updated_at: Updated
+ distrib_type: Source type
+ visibility: Status
+ visibility_types:
+ open: Open
+ hidden: Hidden
+
+ event_log:
+ kind: Event type
+ created_at: Event date and time
+ user: User
+ ip: User IP
+ protocol: Access protocol
+ description: Description
+
+ project:
+ category_id: Category
+ name: Name
+ description: Descripton
+ owner: Owner
+ visibility: Visibility
+ repository_id: Repository
+ repository: Repository
+ created_at: Created
+ updated_at: Updated
+ has_issues: Tracker on
+ srpm: Import code from src.rpm
+
+ rpm:
+ name: Name
+ arch_id: Arch
+ arch: Arch
+ project_id: Project
+ project: Project
+ created_at: Created
+ updated_at: Updated
+
+ role:
+ name: Name
+ on: Slave
+ to: Master
+ use_default: By default
+ use_default_for_owner: Default by owner
+
+ group:
+ name: Name
+ uname: Nickname
+ owner: Owner
+ created_at: Created
+ updated_at: Updated
+
+ user:
+ name: User
+ login: Nickname or Email
+ email: Email
+ uname: Nickname
+ ssh_key: SSH key
+ current_password: Current password
+ role: Role
+ created_at: Created
+ updated_at: Updated
+ role: System role
+ language: Language
+
+ product_build_list:
+ id: Id
+ product: Product
+ status: Status
+ notified_at: Notified at
+
+ build_list:
+ bs_id: Id
+ name: Name
+ container_path: Container path
+ status: Status
+ project_id: Project
+ project: Project
+ arch_id: Architecture
+ arch: Architecture
+ is_circle: Recurrent
+ notified_at: Notified at
+ additional_repos: Additional repository
+ include_repos: Includes repository
+ updated_at: Updated
+ created_at: Created
+ pl: Packet list repository
+ pl_id: Packet list repository
+ bpl: Platform
+ bpl_id: Platform
+ update_type: Update type
+ build_requires: Dependable build requires
+ auto_publish: Automated publising
+ project_version: Version
+ user: User
+
+ build_list/item:
+ name: Name
+ level: Level
+ status: Status
+ version: Version
+ build_list: Build list
+
+ download:
+ name: Name
+ version: Version
+ distro: Source
+ platform: Platform
+ counter: Downloads
+
+ notifications:
+ subjects:
+ new_comment_notification: New comment to your task
+ new_issue_notification: New task added to project
+ new_user_notification: Registered on project «%{ project_name }»
+ issue_assign_notification: New task assigned
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index efacd3794..ba3f3141f 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -41,7 +41,22 @@ ru:
not_access: Нет доступа!
owner: Владелец
confirm: Уверены?
+ back: Назад
+ settings:
+ notifier: Настройки оповещений
+ notifiers:
+ edit_header: Настройки оповещений
processing: Обрабатывается...
+ invalid_content_type: имеет неверный тип
+
+ devise:
+ shared_links:
+ sign_in: Войти
+ sign_up: Зарегистрироваться
+ forgot_password: Забыли пароль?
+ confirm_again: Не получили инструкции по подтверждению?
+ unlock: Не получили инструкции по разблокировке?
+ sign_in_through: Войти через %{provider}
downloads:
title: Статистика закачек пакетов
@@ -129,6 +144,7 @@ ru:
comments:
confirm_delete: Вы уверены, что хотите удалить комментарий?
new_header: Новый комментарий
+ edit_header: Редактирование комментария
platforms:
admin_id: Владелец
@@ -267,7 +283,6 @@ ru:
new_header: Новый продукт
edit_header: Редактирование продукта
confirm_delete: Вы уверены, что хотите удалить этот продукт?
- invalid_content_type: имеет неверный тип
cron_tab_generator:
show: Показать cron tab генератор
@@ -391,6 +406,7 @@ ru:
cancel_fail: 'При отмене сборки произошла ошибка!'
publish_success: 'Сборка поставлена в очередь на публикацию.'
publish_fail: 'При публикации сборки произошла ошибка!'
+ container_published: 'Контейнер размещен в репозитории'
build_server_status:
header: Статус сборочного сервера
@@ -405,6 +421,7 @@ ru:
dependencies_error: зависимости не найдены
success: собран
unknown: ожидает сборки
+ git_error: проблема с гит
statuses:
build_error: ошибка сборки
@@ -422,9 +439,14 @@ ru:
platform_not_found: платформа не найдена
platform_pending: платформа в процессе создания
project_not_found: проект не найден
- project_version_not_found: версия не найден
+ project_version_not_found: версия не найдена
flash:
+ settings:
+ saved: Настройки успешно сохранены
+ save_error: При обновлении настроек произошла ошибка
+
+
subscribe:
saved: Вы подписаны на оповещения для этой задачи
destroyed: Подписка на оповещения для этой задачи убрана
@@ -513,6 +535,7 @@ ru:
unfreeze_error: Не удалось разморозить платформу, попробуйте еще раз
destroyed: Платформа успешно удалена
build_all_success: Все проекты успешно отправлены на сборку
+ clone_success: Клонирование успешно
build_list:
saved: Билд лист для версии '%{project_version}', платформы '%{bpl}' и архитектуры '%{arch}' создан успешно
@@ -566,8 +589,18 @@ ru:
build_list_item: Элемент сборочного листа
download: Статистика
auto_build_list: Автоматическая пересборка пакетов
+ settings:
+ notifier: Настройки оповещений
attributes:
+ settings:
+ notifier:
+ can_notify: Включить оповещения по электронной почте
+ new_comment: Оповещать о новом комментарии в задаче
+ new_comment_reply: Оповещать о новом ответе на мой комментарий
+ new_issue: Оповещать о новых задачах в моих проектах
+ issue_assign: Оповещать, когда на меня выставляют задачу
+
auto_build_list:
project_id: Проект
project: Проект
@@ -672,6 +705,7 @@ ru:
updated_at: Обновлен
has_issues: Включить трэкер
has_wiki: Включить Wiki
+ srpm: Импортировать код из src.rpm
rpm:
name: Название
@@ -707,6 +741,7 @@ ru:
created_at: Создан
updated_at: Обновлен
role: Роль в системе
+ language: Язык
product_build_list:
id: Id
diff --git a/config/routes.rb b/config/routes.rb
index b868e46ea..8a6c0107e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,14 +1,17 @@
Rosa::Application.routes.draw do
# XML RPC
match 'api/xmlrpc' => 'rpc#xe_index'
-
+
devise_for :users, :controllers => {:omniauth_callbacks => 'users/omniauth_callbacks'} do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
-
+
resources :users do
resources :groups, :only => [:new, :create, :index]
get :autocomplete_user_uname, :on => :collection
+ namespace :settings do
+ resource :notifier, :only => [:show, :update]
+ end
end
resources :event_logs, :only => :index
@@ -164,20 +167,24 @@ Rosa::Application.routes.draw do
# Tree
match '/projects/:project_id/git/tree/:treeish(/*path)', :controller => "git/trees", :action => :show, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :tree
-
+
# Commits
match '/projects/:project_id/git/commits/:treeish(/*path)', :controller => "git/commits", :action => :index, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :commits
match '/projects/:project_id/git/commit/:id(.:format)', :controller => "git/commits", :action => :show, :defaults => { :format => :html }, :as => :commit
-
+ # Commit Comments
+ match '/projects/:project_id/git/commit/:commit_id/comments/:id(.:format)', :controller => "comments", :action => :edit, :as => :edit_project_commit_comment, :via => :get
+ match '/projects/:project_id/git/commit/:commit_id/comments/:id(.:format)', :controller => "comments", :action => :update, :as => :project_commit_comment, :via => :put
+ match '/projects/:project_id/git/commit/:commit_id/comments/:id(.:format)', :controller => "comments", :action => :destroy, :via => :delete
+ match '/projects/:project_id/git/commit/:commit_id/comments(.:format)', :controller => "comments", :action => :create, :as => :project_commit_comments, :via => :post
# Blobs
match '/projects/:project_id/git/blob/:treeish/*path', :controller => "git/blobs", :action => :show, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :blob
match '/projects/:project_id/git/commit/blob/:commit_hash/*path', :controller => "git/blobs", :action => :show, :project_name => /[0-9a-zA-Z_.\-]*/, :as => :blob_commit
-
+
# Blame
match '/projects/:project_id/git/blame/:treeish/*path', :controller => "git/blobs", :action => :blame, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :blame
match '/projects/:project_id/git/commit/blame/:commit_hash/*path', :controller => "git/blobs", :action => :blame, :as => :blame_commit
-
- # Raw
+
+ # Raw
match '/projects/:project_id/git/raw/:treeish/*path', :controller => "git/blobs", :action => :raw, :treeish => /[0-9a-zA-Z_.\-]*/, :defaults => { :treeish => :master }, :as => :raw
match '/projects/:project_id/git/commit/raw/:commit_hash/*path', :controller => "git/blobs", :action => :raw, :as => :raw_commit
diff --git a/db/migrate/20111012223306_create_roles.rb b/db/migrate/20111012223306_create_roles.rb
new file mode 100644
index 000000000..b5693219d
--- /dev/null
+++ b/db/migrate/20111012223306_create_roles.rb
@@ -0,0 +1,14 @@
+class CreateRoles < ActiveRecord::Migration
+ def self.up
+ create_table :roles do |t|
+ t.integer :id
+ t.string :name
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :roles
+ end
+end
diff --git a/db/migrate/20111019173246_create_role_lines.rb b/db/migrate/20111019173246_create_role_lines.rb
new file mode 100644
index 000000000..84aa4e3de
--- /dev/null
+++ b/db/migrate/20111019173246_create_role_lines.rb
@@ -0,0 +1,13 @@
+class CreateRoleLines < ActiveRecord::Migration
+ def self.up
+ create_table :role_lines do |t|
+ t.integer :role_id
+ t.integer :relation_id
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :role_lines
+ end
+end
diff --git a/db/migrate/20120111072106_create_settings_notifiers.rb b/db/migrate/20120111072106_create_settings_notifiers.rb
new file mode 100644
index 000000000..b8517a9e9
--- /dev/null
+++ b/db/migrate/20120111072106_create_settings_notifiers.rb
@@ -0,0 +1,19 @@
+class CreateSettingsNotifiers < ActiveRecord::Migration
+ def self.up
+ create_table :settings_notifiers do |t|
+ t.integer :user_id, :null => false
+
+ t.boolean :can_notify, :default => true
+ t.boolean :new_comment, :default => true
+ t.boolean :new_comment_reply, :default => true
+ t.boolean :new_issue, :default => true
+ t.boolean :issue_assign, :default => true
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :settings_notifiers
+ end
+end
diff --git a/db/migrate/20120111080234_change_commentable_id.rb b/db/migrate/20120111080234_change_commentable_id.rb
new file mode 100644
index 000000000..60c3c3268
--- /dev/null
+++ b/db/migrate/20120111080234_change_commentable_id.rb
@@ -0,0 +1,9 @@
+class ChangeCommentableId < ActiveRecord::Migration
+ def self.up
+ change_column :comments, :commentable_id, :string
+ end
+
+ def self.down
+ change_column :comments, :commentable_id, :integer
+ end
+end
diff --git a/db/migrate/20120111135443_add_settings_notifier_to_all_users.rb b/db/migrate/20120111135443_add_settings_notifier_to_all_users.rb
new file mode 100644
index 000000000..de018150a
--- /dev/null
+++ b/db/migrate/20120111135443_add_settings_notifier_to_all_users.rb
@@ -0,0 +1,13 @@
+class AddSettingsNotifierToAllUsers < ActiveRecord::Migration
+ def self.up
+ User.all.each do |user|
+ user.create_notifier
+ end
+ end
+
+ def self.down
+ User.all.each do |user|
+ user.notifier.destroy
+ end
+ end
+end
diff --git a/db/migrate/20120113121748_add_issue_status_default_value.rb b/db/migrate/20120113121748_add_issue_status_default_value.rb
new file mode 100644
index 000000000..bbc58f3cc
--- /dev/null
+++ b/db/migrate/20120113121748_add_issue_status_default_value.rb
@@ -0,0 +1,9 @@
+class AddIssueStatusDefaultValue < ActiveRecord::Migration
+ def self.up
+ change_column :issues, :status, :string, :default => 'open'
+ end
+
+ def self.down
+ change_column :issues, :status, :string, :null => true
+ end
+end
diff --git a/db/migrate/20120113151305_add_package_version_to_build_lists.rb b/db/migrate/20120113151305_add_package_version_to_build_lists.rb
new file mode 100644
index 000000000..d416e3fa5
--- /dev/null
+++ b/db/migrate/20120113151305_add_package_version_to_build_lists.rb
@@ -0,0 +1,9 @@
+class AddPackageVersionToBuildLists < ActiveRecord::Migration
+ def self.up
+ add_column :build_lists, :package_version, :string
+ end
+
+ def self.down
+ remove_column :build_lists, :package_version
+ end
+end
diff --git a/db/migrate/20120113212924_add_commit_hash_to_build_lists.rb b/db/migrate/20120113212924_add_commit_hash_to_build_lists.rb
new file mode 100644
index 000000000..504d49f9a
--- /dev/null
+++ b/db/migrate/20120113212924_add_commit_hash_to_build_lists.rb
@@ -0,0 +1,9 @@
+class AddCommitHashToBuildLists < ActiveRecord::Migration
+ def self.up
+ add_column :build_lists, :commit_hash, :string
+ end
+
+ def self.down
+ remove_column :build_lists, :commit_hash
+ end
+end
diff --git a/db/migrate/20120117110723_add_language_to_users.rb b/db/migrate/20120117110723_add_language_to_users.rb
new file mode 100644
index 000000000..4bf0cec48
--- /dev/null
+++ b/db/migrate/20120117110723_add_language_to_users.rb
@@ -0,0 +1,9 @@
+class AddLanguageToUsers < ActiveRecord::Migration
+ def self.up
+ add_column :users, :language, :string, :default => 'en'
+ end
+
+ def self.down
+ remove_column :users, :language
+ end
+end
diff --git a/db/migrate/20120124101727_add_srpm_columns_to_projects.rb b/db/migrate/20120124101727_add_srpm_columns_to_projects.rb
new file mode 100644
index 000000000..3aa569326
--- /dev/null
+++ b/db/migrate/20120124101727_add_srpm_columns_to_projects.rb
@@ -0,0 +1,11 @@
+class AddSrpmColumnsToProjects < ActiveRecord::Migration
+ def self.up
+ change_table :projects do |t|
+ t.has_attached_file :srpm
+ end
+ end
+
+ def self.down
+ drop_attached_file :projects, :srpm
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 66760c9f1..4ed423246 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -72,6 +72,8 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
t.text "include_repos"
t.integer "user_id"
t.boolean "auto_publish", :default => true
+ t.string "package_version"
+ t.string "commit_hash"
end
add_index "build_lists", ["arch_id"], :name => "index_build_lists_on_arch_id"
@@ -87,7 +89,7 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
end
create_table "comments", :force => true do |t|
- t.integer "commentable_id"
+ t.string "commentable_id"
t.string "commentable_type"
t.integer "user_id"
t.text "body"
@@ -159,13 +161,20 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
t.integer "user_id"
t.string "title"
t.text "body"
- t.string "status"
+ t.string "status", :default => "open"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "issues", ["project_id", "serial_id"], :name => "index_issues_on_project_id_and_serial_id", :unique => true
+ create_table "permissions", :force => true do |t|
+ t.integer "right_id"
+ t.integer "role_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "platforms", :force => true do |t|
t.string "description"
t.string "name"
@@ -237,7 +246,7 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
t.integer "category_id"
t.text "description"
t.string "ancestry"
- t.boolean "has_wiki"
+ t.boolean "has_wiki", :default => false
t.boolean "has_issues", :default => true
end
@@ -263,6 +272,14 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
t.string "owner_type"
end
+ create_table "rights", :force => true do |t|
+ t.string "name", :null => false
+ t.string "controller", :null => false
+ t.string "action", :null => false
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "rpms", :force => true do |t|
t.string "name", :null => false
t.integer "arch_id", :null => false
@@ -274,6 +291,17 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
add_index "rpms", ["project_id", "arch_id"], :name => "index_rpms_on_project_id_and_arch_id"
add_index "rpms", ["project_id"], :name => "index_rpms_on_project_id"
+ create_table "settings_notifiers", :force => true do |t|
+ t.integer "user_id", :null => false
+ t.boolean "can_notify", :default => true
+ t.boolean "new_comment", :default => true
+ t.boolean "new_comment_reply", :default => true
+ t.boolean "new_issue", :default => true
+ t.boolean "issue_assign", :default => true
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "subscribes", :force => true do |t|
t.integer "subscribeable_id"
t.string "subscribeable_type"
@@ -284,9 +312,9 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
create_table "users", :force => true do |t|
t.string "name"
- t.string "email", :default => "", :null => false
- t.string "encrypted_password", :limit => 128, :default => "", :null => false
- t.string "password_salt", :default => "", :null => false
+ t.string "email", :default => "", :null => false
+ t.string "encrypted_password", :limit => 128, :default => "", :null => false
+ t.string "password_salt", :default => "", :null => false
t.string "reset_password_token"
t.string "remember_token"
t.datetime "remember_created_at"
@@ -296,6 +324,7 @@ ActiveRecord::Schema.define(:version => 20120126214447) do
t.string "uname"
t.string "role"
t.integer "own_projects_count", :default => 0, :null => false
+ t.string "language", :default => "en"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index d3c5cce79..88f65117d 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -5,8 +5,9 @@ namespace :import do
desc "Load projects"
task :projects => :environment do
source = ENV['SOURCE'] || 'http://dl.dropbox.com/u/984976/package_list.txt'
- owner = User.find_by_uname(ENV['OWNER_UNAME']) || Group.find_by_uname(ENV['OWNER_UNAME']) || User.first
- platform = Platform.find_by_name(ENV['PLATFORM_NAME']) # 'mandriva2011'
+ #owner = User.find_by_uname(ENV['OWNER_UNAME']) || Group.find_by_uname(ENV['OWNER_UNAME']) || User.first
+ owner = Group.find_by_uname("npp_team")
+ platform = Platform.find_by_name("RosaNPP") # RosaNPP
repo = platform.repositories.first rescue nil
say "START import projects from '#{source}' for '#{owner.uname}'.#{repo ? " To repo '#{platform.name}/#{repo.name}'." : ''}"
ask 'Press enter to continue'
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index b2617a1c7..2ab692666 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -1,3 +1,13 @@
+function disableNotifierCbx(global_cbx) {
+ if ($(global_cbx).attr('checked')) {
+ $('.notify_cbx').removeAttr('disabled');
+ $('.notify_cbx').each(function(i,el) { $(el).prev().removeAttr('disabled'); })
+ } else {
+ $('.notify_cbx').attr('disabled', 'disabled');
+ $('.notify_cbx').each(function(i,el) { $(el).prev().attr('disabled', 'disabled'); })
+ }
+}
+
$(document).ready(function() {
$('select#build_list_pl_id').change(function() {
var platform_id = $(this).val();
@@ -29,4 +39,8 @@ $(document).ready(function() {
}
});
});
+
+ $('#settings_notifier_can_notify').click(function() {
+ disableNotifierCbx($(this));
+ });
});
diff --git a/spec/controllers/build_lists_controller_spec.rb b/spec/controllers/build_lists_controller_spec.rb
index a3e088c63..79035ac97 100644
--- a/spec/controllers/build_lists_controller_spec.rb
+++ b/spec/controllers/build_lists_controller_spec.rb
@@ -27,6 +27,8 @@ describe BuildListsController do
end
shared_examples_for 'create build list' do
+ before {test_git_commit(@project)}
+
it 'should be able to perform new action' do
get :new, :project_id => @project.id
response.should render_template(:new)
@@ -36,6 +38,17 @@ describe BuildListsController do
post :create, {:project_id => @project.id}.merge(@create_params)
response.should redirect_to(@project)
end
+
+ it 'should save correct commit_hash for branch based build' do
+ post :create, {:project_id => @project.id}.merge(@create_params).deep_merge(:build_list => {:project_version => "master_latest"})
+ @project.build_lists.last.commit_hash.should == @project.git_repository.commits('master').last.id
+ end
+
+ 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
+ post :create, {:project_id => @project.id}.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
+ end
end
shared_examples_for 'not create build list' do
@@ -57,7 +70,7 @@ describe BuildListsController do
platform = Factory(:platform_with_repos)
@create_params = {
:build_list => {
- :project_version => 'v1.0',
+ :project_version => 'master_latest',
:pl_id => platform.id,
:update_type => 'security',
:include_repos => [platform.repositories.first.id]
@@ -299,14 +312,23 @@ describe BuildListsController do
let(:build_list) { Factory(:build_list_core) }
describe 'publish_build' do
+ before { test_git_commit(build_list.project); build_list.update_attribute :commit_hash, build_list.project.git_repository.commits('master').last.id }
+
def do_get(status)
- get :publish_build, :id => build_list.bs_id, :status => status
+ get :publish_build, :id => build_list.bs_id, :status => status, :version => '4.7.5.3', :release => '1'
build_list.reload
end
it { do_get(BuildServer::SUCCESS); response.should be_ok }
+ it 'should create correct git tag for correct commit' do
+ do_get(BuildServer::SUCCESS)
+ build_list.project.git_repository.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
+ end
it { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :status).to(BuildList::BUILD_PUBLISHED) }
+ it { lambda{ do_get(BuildServer::SUCCESS) }.should change(build_list, :package_version).to('4.7.5.3-1') }
it { lambda{ do_get(BuildServer::ERROR) }.should change(build_list, :status).to(BuildList::FAILED_PUBLISH) }
+ it { lambda{ do_get(BuildServer::ERROR) }.should_not change(build_list, :package_version) }
it { lambda{ do_get(BuildServer::ERROR) }.should change(build_list, :notified_at) }
end
diff --git a/spec/controllers/comments_controller_for_commit_spec.rb b/spec/controllers/comments_controller_for_commit_spec.rb
new file mode 100644
index 000000000..70daadb17
--- /dev/null
+++ b/spec/controllers/comments_controller_for_commit_spec.rb
@@ -0,0 +1,152 @@
+require 'spec_helper'
+
+shared_examples_for 'user with create comment rights for commits' do
+ it 'should be able to perform create action' do
+ post :create, @create_params
+ response.should redirect_to(commit_path(@project, @commit.id))
+ end
+
+ it 'should create subscribe object into db' do
+ lambda{ post :create, @create_params }.should change{ Comment.count }.by(1)
+ end
+end
+
+shared_examples_for 'user with update own comment rights for commits' do
+ it 'should be able to perform update action' do
+ put :update, {:id => @own_comment.id}.merge(@update_params)
+ response.should redirect_to(commit_path(@project, @commit.id))
+ end
+
+ it 'should update subscribe body' do
+ put :update, {:id => @own_comment.id}.merge(@update_params)
+ @own_comment.reload.body.should == 'updated'
+ end
+end
+
+shared_examples_for 'user with update stranger comment rights for commits' do
+ it 'should be able to perform update action' do
+ put :update, {:id => @comment.id}.merge(@update_params)
+ response.should redirect_to(commit_path(@project, @commit.id))
+ end
+
+ it 'should update comment title' do
+ put :update, {:id => @comment.id}.merge(@update_params)
+ @comment.reload.body.should == 'updated'
+ end
+end
+
+shared_examples_for 'user without update stranger comment rights for commits' do
+ it 'should not be able to perform update action' do
+ put :update, {:id => @comment.id}.merge(@update_params)
+ response.should redirect_to(forbidden_path)
+ end
+
+ it 'should not update comment title' do
+ put :update, {:id => @comment.id}.merge(@update_params)
+ @comment.reload.body.should_not == 'updated'
+ end
+end
+
+shared_examples_for 'user without destroy comment rights for commits' do
+ it 'should not be able to perform destroy action' do
+ delete :destroy, :id => @comment.id, :commit_id => @commit.id, :project_id => @project.id
+ response.should redirect_to(forbidden_path)
+ end
+
+ it 'should not reduce comments count' do
+ lambda{ delete :destroy, :id => @comment.id, :commit_id => @commit.id, :project_id => @project.id }.should change{ Comment.count }.by(0)
+ end
+end
+
+#shared_examples_for 'user with destroy rights' do
+# it 'should be able to perform destroy action' do
+# delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :project_id => @project.id
+# response.should redirect_to([@project, @issue])
+# end
+#
+# it 'should reduce comments count' do
+# lambda{ delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :project_id => @project.id }.should change{ Comment.count }.by(-1)
+# end
+#end
+
+describe CommentsController do
+ before(:each) do
+ stub_rsync_methods
+
+ @project = Factory(:project)
+ %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ?
+ @commit = @project.git_repository.commits.first
+
+ @comment = Factory(:comment)
+ @comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+ @create_params = {:comment => {:body => 'I am a comment!'}, :project_id => @project.id, :commit_id => @commit.id}
+ @update_params = {:comment => {:body => 'updated'}, :project_id => @project.id, :commit_id => @commit.id}
+
+ any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
+
+ @request.env['HTTP_REFERER'] = commit_path(@project, @commit.id)
+ end
+
+ context 'for project admin user' do
+ before(:each) do
+ @user = Factory(:user)
+ set_session_for(@user)
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
+ @own_comment = Factory(:comment, :user => @user)
+ @own_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+ end
+
+ it_should_behave_like 'user with create comment rights for commits'
+ it_should_behave_like 'user with update stranger comment rights for commits'
+ it_should_behave_like 'user with update own comment rights for commits'
+ it_should_behave_like 'user without destroy comment rights for commits'
+ end
+
+ context 'for project owner user' do
+ before(:each) do
+ @user = @project.owner
+ set_session_for(@user)
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
+
+ @own_comment = Factory(:comment, :user => @user)
+ @own_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+ end
+
+ it_should_behave_like 'user with create comment rights for commits'
+ it_should_behave_like 'user with update stranger comment rights for commits'
+ it_should_behave_like 'user with update own comment rights for commits'
+ it_should_behave_like 'user without destroy comment rights for commits'
+ end
+
+ context 'for project reader user' do
+ before(:each) do
+ @user = Factory(:user)
+ set_session_for(@user)
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'reader')
+
+ @own_comment = Factory(:comment, :user => @user)
+ @own_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+ end
+
+ it_should_behave_like 'user with create comment rights for commits'
+ it_should_behave_like 'user without update stranger comment rights for commits'
+ it_should_behave_like 'user with update own comment rights for commits'
+ it_should_behave_like 'user without destroy comment rights for commits'
+ end
+
+ context 'for project writer user' do
+ before(:each) do
+ @user = Factory(:user)
+ set_session_for(@user)
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'writer')
+
+ @own_comment = Factory(:comment, :user => @user)
+ @own_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+ end
+
+ it_should_behave_like 'user with create comment rights for commits'
+ it_should_behave_like 'user without update stranger comment rights for commits'
+ it_should_behave_like 'user with update own comment rights for commits'
+ it_should_behave_like 'user without destroy comment rights for commits'
+ end
+end
diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb
index c93ac57f0..d8cd8d002 100644
--- a/spec/controllers/comments_controller_spec.rb
+++ b/spec/controllers/comments_controller_spec.rb
@@ -49,12 +49,12 @@ end
shared_examples_for 'user without destroy comment rights' do
it 'should not be able to perform destroy action' do
- delete :destroy, :id => @comment.id, :issue_id => @issue.id, :project_id => @project.id
+ delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :project_id => @project.id
response.should redirect_to(forbidden_path)
end
it 'should not reduce comments count' do
- lambda{ delete :destroy, :id => @comment.id, :issue_id => @issue.id, :project_id => @project.id }.should change{ Issue.count }.by(0)
+ lambda{ delete :destroy, :id => @comment.id, :issue_id => @issue.serial_id, :project_id => @project.id }.should change{ Issue.count }.by(0)
end
end
@@ -77,8 +77,8 @@ describe CommentsController do
@issue = Factory(:issue, :project_id => @project.id)
@comment = Factory(:comment, :commentable => @issue)
- @create_params = {:comment => {:body => 'I am a comment!'}, :project_id => @project.id, :issue_id => @issue.id}
- @update_params = {:comment => {:body => 'updated'}, :project_id => @project.id, :issue_id => @issue.id}
+ @create_params = {:comment => {:body => 'I am a comment!'}, :project_id => @project.id, :issue_id => @issue.serial_id}
+ @update_params = {:comment => {:body => 'updated'}, :project_id => @project.id, :issue_id => @issue.serial_id}
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
diff --git a/spec/controllers/settings/notifiers_controller_spec.rb b/spec/controllers/settings/notifiers_controller_spec.rb
new file mode 100644
index 000000000..3ffcced81
--- /dev/null
+++ b/spec/controllers/settings/notifiers_controller_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe Settings::NotifiersController do
+
+end
diff --git a/spec/factories/build_list_factory.rb b/spec/factories/build_list_factory.rb
index 10c4fc3b5..751a6ea09 100644
--- a/spec/factories/build_list_factory.rb
+++ b/spec/factories/build_list_factory.rb
@@ -8,6 +8,7 @@ Factory.define(:build_list) do |p|
p.build_requires true
p.update_type 'security'
p.include_repos {|bl| bl.pl.repositories.map(&:id)}
+ p.commit_hash '1234567890abcdef1234567890abcdef12345678'
end
Factory.define(:build_list_core, :parent => :build_list) do |p|
diff --git a/spec/factories/settings_notifiers.rb b/spec/factories/settings_notifiers.rb
new file mode 100644
index 000000000..d189db60e
--- /dev/null
+++ b/spec/factories/settings_notifiers.rb
@@ -0,0 +1,6 @@
+# Read about factories at http://github.com/thoughtbot/factory_girl
+
+FactoryGirl.define do
+ factory :notifier do
+ end
+end
\ No newline at end of file
diff --git a/spec/helpers/settings/notifiers_helper_spec.rb b/spec/helpers/settings/notifiers_helper_spec.rb
new file mode 100644
index 000000000..9b16f8bda
--- /dev/null
+++ b/spec/helpers/settings/notifiers_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Settings::NotifiersHelper. For example:
+#
+# describe Settings::NotifiersHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# helper.concat_strings("this","that").should == "this that"
+# end
+# end
+# end
+describe Settings::NotifiersHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb
index 8d004b3ed..ff86fcc9d 100644
--- a/spec/mailers/user_mailer_spec.rb
+++ b/spec/mailers/user_mailer_spec.rb
@@ -2,4 +2,118 @@ require "spec_helper"
describe UserMailer do
pending "add some examples to (or delete) #{__FILE__}"
+
+ context 'On Issue create' do
+ before(:each) do
+ stub_rsync_methods
+
+ @project = Factory(:project)
+ @issue_user = Factory(:user)
+
+ any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
+
+ @issue = Factory(:issue, :project_id => @project.id, :user_id => @issue_user.id)
+ @email = UserMailer.new_issue_notification(@issue, @issue_user).deliver
+ end
+
+ it 'should have correct subject' do
+ @email.subject.should == I18n.t("notifications.subjects.new_issue_notification")
+ end
+
+ it 'should render receiver email' do
+ @email.to.should == [@issue_user.email]
+ end
+
+ it 'should render the sender email' do
+ @email.from.should == [APP_CONFIG['do-not-reply-email']]
+ end
+
+ it 'should assign user name' do
+ @email.body.encoded.should match(@issue_user.name)
+ end
+
+ it 'should assign issue project name' do
+ @email.body.encoded.should match(@issue.project.name)
+ end
+
+ it 'should assign issue title' do
+ @email.body.encoded.should match(@issue.title)
+ end
+ end
+
+ context 'On Issue assign' do
+ before(:each) do
+ stub_rsync_methods
+
+ @project = Factory(:project)
+ @issue_user = Factory(:user)
+ @user = Factory(:user)
+
+ any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
+
+ @issue = Factory(:issue, :project_id => @project.id, :user_id => @issue_user.id)
+ @email = UserMailer.issue_assign_notification(@issue, @user).deliver
+ end
+
+ it 'should have correct subject' do
+ @email.subject.should == I18n.t("notifications.subjects.issue_assign_notification")
+ end
+
+ it 'should render receiver email' do
+ @email.to.should == [@user.email]
+ end
+
+ it 'should render the sender email' do
+ @email.from.should == [APP_CONFIG['do-not-reply-email']]
+ end
+
+ it 'should assign user name' do
+ @email.body.encoded.should match(@user.name)
+ end
+
+ it 'should assign issue title' do
+ @email.body.encoded.should match(@issue.title)
+ end
+ end
+
+
+ context 'On Comment create' do
+ before(:each) do
+ stub_rsync_methods
+
+ @project = Factory(:project)
+ @issue_user = Factory(:user)
+ @user = Factory(:user)
+
+ any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
+
+ @issue = Factory(:issue, :project_id => @project.id, :user_id => @issue_user.id)
+ @comment = Factory(:comment, :commentable => @issue, :user_id => @user.id)
+ @email = UserMailer.new_comment_notification(@comment, @issue_user).deliver
+ end
+
+ it 'should have correct subject' do
+ @email.subject.should == I18n.t("notifications.subjects.new_comment_notification")
+ end
+
+ it 'should render receiver email' do
+ @email.to.should == [@issue_user.email]
+ end
+
+ it 'should render the sender email' do
+ @email.from.should == [APP_CONFIG['do-not-reply-email']]
+ end
+
+ it 'should assign user name' do
+ @email.body.encoded.should match(@issue_user.name)
+ end
+
+ it 'should assign comment body' do
+ @email.body.encoded.should match(@comment.body)
+ end
+
+ it 'should assign issue title' do
+ @email.body.encoded.should match(@issue.title)
+ end
+ end
end
diff --git a/spec/models/cancan_spec.rb b/spec/models/cancan_spec.rb
index e245c19ff..bafc774d1 100644
--- a/spec/models/cancan_spec.rb
+++ b/spec/models/cancan_spec.rb
@@ -91,7 +91,7 @@ describe CanCan do
@ability.should be_able_to(:read, @admin)
end
- it "shoud be able to read index AutoBuildList" do
+ pending "shoud be able to read index AutoBuildList" do
@ability.should be_able_to(:index, AutoBuildList)
end
diff --git a/spec/models/comment_for_commit_spec.rb b/spec/models/comment_for_commit_spec.rb
new file mode 100644
index 000000000..938c4db7e
--- /dev/null
+++ b/spec/models/comment_for_commit_spec.rb
@@ -0,0 +1,135 @@
+require 'spec_helper'
+require "cancan/matchers"
+
+def set_comments_data_for_commit
+ @ability = Ability.new(@user)
+
+ @project = Factory(:project)
+ %x(cp -Rf #{Rails.root}/spec/tests.git/* #{@project.git_repository.path}) # maybe FIXME ?
+ @commit = @project.git_repository.commits.first
+
+ @comment = Factory(:comment, :user => @user)
+ @comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id)
+
+ @stranger_comment = Factory(:comment, :user => @stranger)
+ @stranger_comment.update_attributes(:commentable_type => @commit.class.name, :commentable_id => @commit.id, :project => @project)
+
+ @create_params = {:commentable_type => @commit.class.name, :commentable_id => @commit.id, :user => @user, :project => @project}
+
+ any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
+end
+
+describe Comment do
+ context 'for global admin user' do
+ before(:each) do
+ @user = Factory(:admin)
+ @stranger = Factory(:user)
+
+ set_comments_data_for_commit
+ end
+
+ it 'should create comment' do
+ @ability.should be_able_to(:create, Comment.new(@create_params))
+ end
+
+ pending "sends an e-mail" do
+ ActionMailer::Base.deliveries.last.to.include?(@stranger.email).should == true
+ end
+
+ it 'should update comment' do
+ @ability.should be_able_to(:update, @comment)
+ end
+
+ it 'should update stranger comment' do
+ @ability.should be_able_to(:update, @stranger_comment)
+ end
+
+ it 'should destroy own comment' do
+ @ability.should be_able_to(:destroy, @comment)
+ end
+
+ it 'should destroy stranger comment' do
+ @ability.should be_able_to(:destroy, @stranger_comment)
+ end
+ end
+
+ context 'for project admin user' do
+ before(:each) do
+ @user = Factory(:user)
+ @stranger = Factory(:user)
+
+ set_comments_data_for_commit
+
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
+ end
+
+ it 'should create comment' do
+ @ability.should be_able_to(:create, Comment.new(@create_params))
+ end
+
+ it 'should update comment' do
+ @ability.should be_able_to(:update, @comment)
+ end
+
+ it 'should update stranger comment' do
+ @ability.should be_able_to(:update, @stranger_comment)
+ end
+
+ it 'should not destroy comment' do
+ @ability.should_not be_able_to(:destroy, @comment)
+ end
+ end
+
+ context 'for project owner user' do
+ before(:each) do
+ @user = Factory(:user)
+ @stranger = Factory(:user)
+
+ set_comments_data_for_commit
+
+ @project.update_attribute(:owner, @user)
+ @project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
+ end
+
+ it 'should create comment' do
+ @ability.should be_able_to(:create, Comment.new(@create_params))
+ end
+
+ it 'should update comment' do
+ @ability.should be_able_to(:update, @comment)
+ end
+
+ it 'should update stranger comment' do
+ @ability.should be_able_to(:update, @stranger_comment)
+ end
+
+ it 'should not destroy comment' do
+ @ability.should_not be_able_to(:destroy, @comment)
+ end
+ end
+
+ context 'for simple user' do
+ before(:each) do
+ @user = Factory(:user)
+ @stranger = Factory(:user)
+
+ set_comments_data_for_commit
+ end
+
+ it 'should create comment' do
+ @ability.should be_able_to(:create, Comment.new(@create_params))
+ end
+
+ it 'should update comment' do
+ @ability.should be_able_to(:update, @comment)
+ end
+
+ it 'should not update stranger comment' do
+ @ability.should_not be_able_to(:update, @stranger_comment)
+ end
+
+ it 'should not destroy comment' do
+ @ability.should_not be_able_to(:destroy, @comment)
+ end
+ end
+end
diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb
index 0b969c134..a8b8b41dc 100644
--- a/spec/models/comment_spec.rb
+++ b/spec/models/comment_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
require "cancan/matchers"
-def set_testable_data
+def set_commentable_data
@ability = Ability.new(@user)
@project = Factory(:project)
@@ -19,13 +19,17 @@ describe Comment do
@user = Factory(:admin)
@stranger = Factory(:user)
- set_testable_data
+ set_commentable_data
end
it 'should create comment' do
@ability.should be_able_to(:create, Comment.new(:commentable => @issue, :user => @user))
end
+ pending "sends an e-mail" do
+ ActionMailer::Base.deliveries.last.to.include?(@stranger.email).should == true
+ end
+
it 'should update comment' do
@ability.should be_able_to(:update, @comment)
end
@@ -35,7 +39,7 @@ describe Comment do
end
it 'should destroy own comment' do
- @ability.should be_able_to(:destroy, @comment)
+ @ability.should be_able_to(:destroy, @comment)
end
it 'should destroy stranger comment' do
@@ -48,7 +52,7 @@ describe Comment do
@user = Factory(:user)
@stranger = Factory(:user)
- set_testable_data
+ set_commentable_data
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
end
@@ -75,7 +79,7 @@ describe Comment do
@user = Factory(:user)
@stranger = Factory(:user)
- set_testable_data
+ set_commentable_data
@project.update_attribute(:owner, @user)
@project.relations.create!(:object_type => 'User', :object_id => @user.id, :role => 'admin')
@@ -103,7 +107,7 @@ describe Comment do
@user = Factory(:user)
@stranger = Factory(:user)
- set_testable_data
+ set_commentable_data
end
it 'should create comment' do
diff --git a/spec/models/settings/notifier_spec.rb b/spec/models/settings/notifier_spec.rb
new file mode 100644
index 000000000..fb73cfe7d
--- /dev/null
+++ b/spec/models/settings/notifier_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe Settings::Notifier do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index a79b3ce74..095a7030f 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -37,6 +37,11 @@ def stub_rsync_methods
any_instance_of(Platform, :umount_directory_for_rsync => true)
end
+def test_git_commit(project)
+ project.git_repository.repo.index.add('test', 'TEST')
+ project.git_repository.repo.index.commit('Test commit')
+end
+
Delayed::Worker.delay_jobs = false # Execute all jobs realtime
# Add testing root_path
diff --git a/spec/tests.git/HEAD b/spec/tests.git/HEAD
new file mode 100644
index 000000000..df9ee5473
--- /dev/null
+++ b/spec/tests.git/HEAD
@@ -0,0 +1 @@
+bdc8b580b5b583aeb43efb19aac2ab8ce5566dff
diff --git a/spec/tests.git/config b/spec/tests.git/config
new file mode 100644
index 000000000..d38f8c6fe
--- /dev/null
+++ b/spec/tests.git/config
@@ -0,0 +1,11 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[remote "origin"]
+ fetch = +refs/heads/*:refs/remotes/origin/*
+ url = git://github.com/tpope/vim-ragtag.git
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
diff --git a/spec/tests.git/description b/spec/tests.git/description
new file mode 100644
index 000000000..498b267a8
--- /dev/null
+++ b/spec/tests.git/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/spec/tests.git/hooks/applypatch-msg.sample b/spec/tests.git/hooks/applypatch-msg.sample
new file mode 100755
index 000000000..8b2a2fe84
--- /dev/null
+++ b/spec/tests.git/hooks/applypatch-msg.sample
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit. The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff --git a/spec/tests.git/hooks/commit-msg.sample b/spec/tests.git/hooks/commit-msg.sample
new file mode 100755
index 000000000..b58d1184a
--- /dev/null
+++ b/spec/tests.git/hooks/commit-msg.sample
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message. The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit. The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
+ echo >&2 Duplicate Signed-off-by lines.
+ exit 1
+}
diff --git a/spec/tests.git/hooks/post-commit.sample b/spec/tests.git/hooks/post-commit.sample
new file mode 100755
index 000000000..22668216a
--- /dev/null
+++ b/spec/tests.git/hooks/post-commit.sample
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script that is called after a successful
+# commit is made.
+#
+# To enable this hook, rename this file to "post-commit".
+
+: Nothing
diff --git a/spec/tests.git/hooks/post-receive.sample b/spec/tests.git/hooks/post-receive.sample
new file mode 100755
index 000000000..7a83e17ab
--- /dev/null
+++ b/spec/tests.git/hooks/post-receive.sample
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script for the "post-receive" event.
+#
+# The "post-receive" script is run after receive-pack has accepted a pack
+# and the repository has been updated. It is passed arguments in through
+# stdin in the form
+#
+# For example:
+# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
+#
+# see contrib/hooks/ for a sample, or uncomment the next line and
+# rename the file to "post-receive".
+
+#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
diff --git a/spec/tests.git/hooks/post-update.sample b/spec/tests.git/hooks/post-update.sample
new file mode 100755
index 000000000..ec17ec193
--- /dev/null
+++ b/spec/tests.git/hooks/post-update.sample
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff --git a/spec/tests.git/hooks/pre-applypatch.sample b/spec/tests.git/hooks/pre-applypatch.sample
new file mode 100755
index 000000000..b1f187c2e
--- /dev/null
+++ b/spec/tests.git/hooks/pre-applypatch.sample
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff --git a/spec/tests.git/hooks/pre-commit.sample b/spec/tests.git/hooks/pre-commit.sample
new file mode 100755
index 000000000..b187c4bb1
--- /dev/null
+++ b/spec/tests.git/hooks/pre-commit.sample
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+ # Note that the use of brackets around a tr range is ok here, (it's
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
+ # the square bracket bytes happen to fall in the designated range.
+ test "$(git diff --cached --name-only --diff-filter=A -z $against |
+ LC_ALL=C tr -d '[ -~]\0')"
+then
+ echo "Error: Attempt to add a non-ascii file name."
+ echo
+ echo "This can cause problems if you want to work"
+ echo "with people on other platforms."
+ echo
+ echo "To be portable it is advisable to rename the file ..."
+ echo
+ echo "If you know what you are doing you can disable this"
+ echo "check using:"
+ echo
+ echo " git config hooks.allownonascii true"
+ echo
+ exit 1
+fi
+
+exec git diff-index --check --cached $against --
diff --git a/spec/tests.git/hooks/pre-rebase.sample b/spec/tests.git/hooks/pre-rebase.sample
new file mode 100755
index 000000000..f0f6da314
--- /dev/null
+++ b/spec/tests.git/hooks/pre-rebase.sample
@@ -0,0 +1,172 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+ topic="refs/heads/$2"
+else
+ topic=`git symbolic-ref HEAD` ||
+ exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+ ;;
+*)
+ exit 0 ;# we do not interrupt others.
+ ;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master. Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+ echo >&2 "No such branch $topic"
+ exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+ echo >&2 "$topic is fully merged to master; better remove it."
+ exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next? If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+ not_in_topic=`git rev-list "^$topic" master`
+ if test -z "$not_in_topic"
+ then
+ echo >&2 "$topic is already up-to-date with master"
+ exit 1 ;# we could allow it, but there is no point.
+ else
+ exit 0
+ fi
+else
+ not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+ /usr/bin/perl -e '
+ my $topic = $ARGV[0];
+ my $msg = "* $topic has commits already merged to public branch:\n";
+ my (%not_in_next) = map {
+ /^([0-9a-f]+) /;
+ ($1 => 1);
+ } split(/\n/, $ARGV[1]);
+ for my $elem (map {
+ /^([0-9a-f]+) (.*)$/;
+ [$1 => $2];
+ } split(/\n/, $ARGV[2])) {
+ if (!exists $not_in_next{$elem->[0]}) {
+ if ($msg) {
+ print STDERR $msg;
+ undef $msg;
+ }
+ print STDERR " $elem->[1]\n";
+ }
+ }
+ ' "$topic" "$not_in_next" "$not_in_master"
+ exit 1
+fi
+
+exit 0
+
+<<\DOC_END
+################################################################
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+ merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+ it is deleted. If you need to build on top of it to correct
+ earlier mistakes, a new topic branch is created by forking at
+ the tip of the "master". This is not strictly necessary, but
+ it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+ branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next". Young
+ topic branches can have stupid mistakes you would rather
+ clean up before publishing, and things that have not been
+ merged into other branches can be easily rebased without
+ affecting other people. But once it is published, you would
+ not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+ Then you can delete it. More importantly, you should not
+ build on top of it -- other people may already want to
+ change things related to the topic as patches against your
+ "master", so if you need further changes, it is better to
+ fork the topic (perhaps with the same name) afresh from the
+ tip of "master".
+
+Let's look at this example:
+
+ o---o---o---o---o---o---o---o---o---o "next"
+ / / / /
+ / a---a---b A / /
+ / / / /
+ / / c---c---c---c B /
+ / / / \ /
+ / / / b---b C \ /
+ / / / / \ /
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished. It has been fully merged up to "master" and "next",
+ and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+ git rev-list ^master ^topic next
+ git rev-list ^master next
+
+ if these match, topic has not merged in next at all.
+
+To compute (2):
+
+ git rev-list master..topic
+
+ if this is empty, it is fully merged to "master".
+
+DOC_END
diff --git a/spec/tests.git/hooks/prepare-commit-msg.sample b/spec/tests.git/hooks/prepare-commit-msg.sample
new file mode 100755
index 000000000..f093a02ec
--- /dev/null
+++ b/spec/tests.git/hooks/prepare-commit-msg.sample
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source. The hook's purpose is to edit the commit
+# message file. If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples. The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output. It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited. This is rarely a good idea.
+
+case "$2,$3" in
+ merge,)
+ /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+# /usr/bin/perl -i.bak -pe '
+# print "\n" . `git diff --cached --name-status -r`
+# if /^#/ && $first++ == 0' "$1" ;;
+
+ *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff --git a/spec/tests.git/hooks/update.sample b/spec/tests.git/hooks/update.sample
new file mode 100755
index 000000000..71ab04edc
--- /dev/null
+++ b/spec/tests.git/hooks/update.sample
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+# This boolean sets whether unannotated tags will be allowed into the
+# repository. By default they won't be.
+# hooks.allowdeletetag
+# This boolean sets whether deleting tags will be allowed in the
+# repository. By default they won't be.
+# hooks.allowmodifytag
+# This boolean sets whether a tag may be modified after creation. By default
+# it won't be.
+# hooks.allowdeletebranch
+# This boolean sets whether deleting branches will be allowed in the
+# repository. By default they won't be.
+# hooks.denycreatebranch
+# This boolean sets whether remotely creating branches will be denied
+# in the repository. By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+ echo "Don't run this script from the command line." >&2
+ echo " (if you want, you could supply GIT_DIR then run" >&2
+ echo " $0 [ )" >&2
+ exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+ echo "Usage: $0 ][ " >&2
+ exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+ echo "*** Project description file hasn't been set" >&2
+ exit 1
+ ;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+ newrev_type=delete
+else
+ newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+ refs/tags/*,commit)
+ # un-annotated tag
+ short_refname=${refname##refs/tags/}
+ if [ "$allowunannotated" != "true" ]; then
+ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,delete)
+ # delete tag
+ if [ "$allowdeletetag" != "true" ]; then
+ echo "*** Deleting a tag is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,tag)
+ # annotated tag
+ if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+ then
+ echo "*** Tag '$refname' already exists." >&2
+ echo "*** Modifying a tag is not allowed in this repository." >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,commit)
+ # branch
+ if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+ echo "*** Creating a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,delete)
+ # delete branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/remotes/*,commit)
+ # tracking branch
+ ;;
+ refs/remotes/*,delete)
+ # delete tracking branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ # Anything else (is there anything else?)
+ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+ exit 1
+ ;;
+esac
+
+# --- Finished
+exit 0
diff --git a/spec/tests.git/index b/spec/tests.git/index
new file mode 100644
index 000000000..29cca27d4
Binary files /dev/null and b/spec/tests.git/index differ
diff --git a/spec/tests.git/info/exclude b/spec/tests.git/info/exclude
new file mode 100644
index 000000000..a5196d1be
--- /dev/null
+++ b/spec/tests.git/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/spec/tests.git/logs/HEAD b/spec/tests.git/logs/HEAD
new file mode 100644
index 000000000..f47abecdc
--- /dev/null
+++ b/spec/tests.git/logs/HEAD
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 bdc8b580b5b583aeb43efb19aac2ab8ce5566dff Alexander 1325695134 +0600 clone: from git://github.com/tpope/vim-ragtag.git
+bdc8b580b5b583aeb43efb19aac2ab8ce5566dff bdc8b580b5b583aeb43efb19aac2ab8ce5566dff Alexander 1325695134 +0600 checkout: moving from master to bdc8b580b5b583aeb43efb19aac2ab8ce5566dff
diff --git a/spec/tests.git/logs/refs/heads/master b/spec/tests.git/logs/refs/heads/master
new file mode 100644
index 000000000..9219de536
--- /dev/null
+++ b/spec/tests.git/logs/refs/heads/master
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 bdc8b580b5b583aeb43efb19aac2ab8ce5566dff Alexander 1325695134 +0600 clone: from git://github.com/tpope/vim-ragtag.git
diff --git a/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.idx b/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.idx
new file mode 100644
index 000000000..46bd6036d
Binary files /dev/null and b/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.idx differ
diff --git a/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.pack b/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.pack
new file mode 100644
index 000000000..593982972
Binary files /dev/null and b/spec/tests.git/objects/pack/pack-5185f74f028bf49d2611c9fea56570138a196143.pack differ
diff --git a/spec/tests.git/packed-refs b/spec/tests.git/packed-refs
new file mode 100644
index 000000000..b48a6248c
--- /dev/null
+++ b/spec/tests.git/packed-refs
@@ -0,0 +1,5 @@
+# pack-refs with: peeled
+30aefeac002db3ec08ff278bd76290645469611e refs/tags/v2.0
+^644c62ad7bc7d9a4a5f19f5e8c41ef910782178b
+235e4467107467feacc50553bbeda15e9bf99f57 refs/tags/v1.11
+bdc8b580b5b583aeb43efb19aac2ab8ce5566dff refs/remotes/origin/master
diff --git a/spec/tests.git/refs/heads/master b/spec/tests.git/refs/heads/master
new file mode 100644
index 000000000..df9ee5473
--- /dev/null
+++ b/spec/tests.git/refs/heads/master
@@ -0,0 +1 @@
+bdc8b580b5b583aeb43efb19aac2ab8ce5566dff
diff --git a/spec/tests.git/refs/remotes/origin/HEAD b/spec/tests.git/refs/remotes/origin/HEAD
new file mode 100644
index 000000000..6efe28fff
--- /dev/null
+++ b/spec/tests.git/refs/remotes/origin/HEAD
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
]