project.rb 5.5 KB
Newer Older
G
gitlabhq 已提交
1 2 3
require "grit"

class Project < ActiveRecord::Base
4 5 6 7 8
  PROJECT_N = 0
  PROJECT_R = 1
  PROJECT_RW = 2
  PROJECT_RWA = 3

G
gitlabhq 已提交
9 10
  belongs_to :owner, :class_name => "User"

D
Dmitriy Zaporozhets 已提交
11
  has_many :merge_requests, :dependent => :destroy
V
VSizov 已提交
12
  has_many :issues, :dependent => :destroy, :order => "position"
G
gitlabhq 已提交
13 14 15
  has_many :users_projects, :dependent => :destroy
  has_many :users, :through => :users_projects
  has_many :notes, :dependent => :destroy
G
gitlabhq 已提交
16
  has_many :snippets, :dependent => :destroy
G
gitlabhq 已提交
17

A
Aleksei Kvitinskii 已提交
18 19
  acts_as_taggable

G
gitlabhq 已提交
20 21 22 23 24 25 26 27
  validates :name,
            :uniqueness => true,
            :presence => true,
            :length   => { :within => 0..255 }

  validates :path,
            :uniqueness => true,
            :presence => true,
G
gitlabhq 已提交
28 29
            :format => { :with => /^[a-zA-Z0-9_\-]*$/,
                         :message => "only letters, digits & '_' '-' allowed" },
G
gitlabhq 已提交
30
            :length   => { :within => 0..255 }
N
Nihad Abbasov 已提交
31

G
gitlabhq 已提交
32 33 34 35 36 37
  validates :description,
            :length   => { :within => 0..2000 }

  validates :code,
            :presence => true,
            :uniqueness => true,
G
gitlabhq 已提交
38 39
            :format => { :with => /^[a-zA-Z0-9_\-]*$/,
                         :message => "only letters, digits & '_' '-' allowed"  },
G
gitlabhq 已提交
40
            :length   => { :within => 3..255 }
G
gitlabhq 已提交
41

G
gitlabhq 已提交
42 43 44
  validates :owner,
            :presence => true

V
Valera Sizov 已提交
45
  validate :check_limit
G
gitlabhq 已提交
46 47
  validate :repo_name

48 49
  after_destroy :destroy_repository
  after_save :update_repository
G
gitlabhq 已提交
50

V
Valera Sizov 已提交
51
  attr_protected :private_flag, :owner_id
G
gitlabhq 已提交
52 53 54

  scope :public_only, where(:private_flag => false)

55 56 57 58 59 60 61 62 63 64

  def self.access_options
    {
      "Denied" => PROJECT_N,
      "Read"   => PROJECT_R,
      "Report" => PROJECT_RW,
      "Admin"  => PROJECT_RWA
    }
  end

D
Dmitriy Zaporozhets 已提交
65 66 67 68 69
  def repository
    @repository ||= Repository.new(self)
  end

  delegate :repo,
70 71
    :url_to_repo,
    :path_to_repo,
72 73
    :update_repository,
    :destroy_repository,
D
Dmitriy Zaporozhets 已提交
74 75 76 77 78 79 80 81 82 83
    :tags,
    :repo_exists?,
    :commit,
    :commits,
    :tree,
    :heads,
    :commits_since,
    :fresh_commits,
    :to => :repository, :prefix => nil

G
gitlabhq 已提交
84 85 86 87
  def to_param
    code
  end

88 89 90 91 92
  def team_member_by_name_or_email(email = nil, name = nil)
    user = users.where("email like ? or name like ?", email, name).first
    users_projects.find_by_user_id(user.id) if user
  end

G
gitlabhq 已提交
93 94 95 96 97 98 99 100
  def fresh_issues(n)
    issues.includes(:project, :author).order("created_at desc").first(n)
  end

  def fresh_notes(n)
    notes.inc_author_project.order("created_at desc").first(n)
  end

G
gitlabhq 已提交
101
  def common_notes
G
gitlabhq 已提交
102
    notes.where(:noteable_type => ["", nil]).inc_author_project
G
gitlabhq 已提交
103 104
  end

105 106
  def build_commit_note(commit)
    notes.new(:noteable_id => commit.id, :noteable_type => "Commit")
G
gitlabhq 已提交
107
  end
N
Nihad Abbasov 已提交
108

109 110
  def commit_notes(commit)
    notes.where(:noteable_id => commit.id, :noteable_type => "Commit")
G
gitlabhq 已提交
111
  end
N
Nihad Abbasov 已提交
112

D
Dmitriy Zaporozhets 已提交
113 114 115 116
  def has_commits?
    !!commit
  end

G
gitlabhq 已提交
117 118 119 120 121 122 123 124 125 126
  def add_access(user, *access)
    opts = { :user => user }
    access.each { |name| opts.merge!(name => true) }
    users_projects.create(opts)
  end

  def reset_access(user)
    users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
  end

127 128 129 130
  def repository_readers
    keys = Key.joins({:user => :users_projects}).
      where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_R)
    keys.map(&:identifier)
G
gitlabhq 已提交
131 132
  end

133
  def repository_writers
134 135
    keys = Key.joins({:user => :users_projects}).
      where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_RW)
G
gitlabhq 已提交
136 137 138 139
    keys.map(&:identifier)
  end

  def readers
140 141 142 143 144
    @readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user)
  end

  def writers
    @writers ||= users_projects.includes(:user).where(:project_access => [PROJECT_RW, PROJECT_RWA]).map(&:user)
G
gitlabhq 已提交
145 146 147
  end

  def admins
148
    @admins ||= users_projects.includes(:user).where(:project_access => PROJECT_RWA).map(&:user)
G
gitlabhq 已提交
149 150
  end

G
gitlabhq 已提交
151 152 153 154
  def root_ref 
    "master"
  end

G
gitlabhq 已提交
155 156 157 158 159 160 161 162
  def public?
    !private_flag
  end

  def private?
    private_flag
  end

N
Nihad Abbasov 已提交
163
  def last_activity
G
gitlabhq 已提交
164
    updates(1).first
N
Nihad Abbasov 已提交
165
  rescue
G
gitlabhq 已提交
166 167 168 169 170 171 172
    nil
  end

  def last_activity_date
    last_activity.try(:created_at)
  end

D
Dmitriy Zaporozhets 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
  # Get project updates from cache
  # or calculate. 
  def cached_updates(limit, expire = 2.minutes)
    activities_key = "project_#{id}_activities"
    cached_activities = Rails.cache.read(activities_key)
    if cached_activities
      activities = cached_activities
    else
      activities = updates(limit)
      Rails.cache.write(activities_key, activities, :expires_in => 60.seconds)
    end

    activities
  end

  # Get 20 events for project like
  # commits, issues or notes
G
gitlabhq 已提交
190
  def updates(n = 3)
N
Nihad Abbasov 已提交
191
    [
G
gitlabhq 已提交
192
      fresh_commits(n),
G
gitlabhq 已提交
193 194
      fresh_issues(n),
      fresh_notes(n)
G
gitlabhq 已提交
195 196
    ].compact.flatten.sort do |x, y|
      y.created_at <=> x.created_at
G
gitlabhq 已提交
197
    end[0...n]
G
gitlabhq 已提交
198 199
  end

V
Valera Sizov 已提交
200 201
  def check_limit
    unless owner.can_create_project?
G
gitlabhq 已提交
202
      errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
V
Valera Sizov 已提交
203
    end
N
Nihad Abbasov 已提交
204
  rescue
G
gitlabhq 已提交
205
    errors[:base] << ("Cant check your ability to create project")
V
Valera Sizov 已提交
206 207
  end

G
gitlabhq 已提交
208
  def repo_name
209 210
    if path == "gitolite-admin"
      errors.add(:path, " like 'gitolite-admin' is not allowed")
G
gitlabhq 已提交
211 212 213
    end
  end

G
gitlabhq 已提交
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
  def valid_repo?
    repo
  rescue
    errors.add(:path, "Invalid repository path")
    false
  end
end
# == Schema Information
#
# Table name: projects
#
#  id           :integer         not null, primary key
#  name         :string(255)
#  path         :string(255)
#  description  :text
#  created_at   :datetime
#  updated_at   :datetime
#  private_flag :boolean         default(TRUE), not null
#  code         :string(255)
V
Valera Sizov 已提交
233
#  owner_id     :integer
G
gitlabhq 已提交
234 235
#