1 class Commit < ActiveRecord::Base
4 def self.git_check_ref_format(e)
5 if !e or e.empty? or e[0] == '-' or e[0] == '$'
9 `git check-ref-format --allow-onelevel #{e.shellescape}`
14 def self.find_commit_range(current_user, repository, minimum, maximum, exclude)
15 if minimum and minimum.empty?
19 if minimum and !git_check_ref_format(minimum)
20 logger.warn "find_commit_range called with invalid minimum revision: '#{minimum}'"
24 if maximum and !git_check_ref_format(maximum)
25 logger.warn "find_commit_range called with invalid maximum revision: '#{maximum}'"
33 # Get list of actual repository directories under management
34 on_disk_repos = repositories
36 # Get list of repository objects readable by user
37 readable = Repository.readable_by(current_user)
39 # filter repository objects on requested repository name
41 readable = readable.where(name: repository)
46 if on_disk_repos[r.name]
47 ENV['GIT_DIR'] = on_disk_repos[r.name][:git_dir]
49 # We've filtered for invalid characters, so we can pass the contents of
50 # minimum and maximum safely on the command line
52 # Get the commit hash for the upper bound
54 IO.foreach("|git rev-list --max-count=1 #{maximum.shellescape} --") do |line|
58 # If not found or string is invalid, nothing else to do
59 next if !max_hash or !git_check_ref_format(max_hash)
61 resolved_exclude = nil
65 if git_check_ref_format(e)
66 IO.foreach("|git rev-list --max-count=1 #{e.shellescape} --") do |line|
67 resolved_exclude.push(line.strip)
70 logger.warn "find_commit_range called with invalid exclude invalid characters: '#{exclude}'"
77 # Get the commit hash for the lower bound
79 IO.foreach("|git rev-list --max-count=1 #{minimum.shellescape} --") do |line|
83 # If not found or string is invalid, nothing else to do
84 next if !min_hash or !git_check_ref_format(min_hash)
86 # Now find all commits between them
87 IO.foreach("|git rev-list #{min_hash.shellescape}..#{max_hash.shellescape} --") do |line|
89 commits.push(hash) if !resolved_exclude or !resolved_exclude.include? hash
92 commits.push(min_hash) if !resolved_exclude or !resolved_exclude.include? min_hash
94 commits.push(max_hash) if !resolved_exclude or !resolved_exclude.include? max_hash
97 logger.warn "Repository #{r.name} exists in table but not found on disk"
101 if !commits or commits.empty?
108 # Import all commits from configured git directory into the commits
112 repositories.each do |repo_name, repo|
113 stat = { true => 0, false => 0 }
114 ENV['GIT_DIR'] = repo[:git_dir]
115 IO.foreach("|git rev-list --format=oneline --all") do |line|
116 sha1, message = line.strip.split " ", 2
118 Commit.find_or_create_by_repository_name_and_sha1_and_message(repo_name, sha1, message[0..254]) do
121 stat[!!imported] += 1
122 if (stat[true] + stat[false]) % 100 == 0
123 if $stdout.tty? or ARGV[0] == '-v'
124 puts "#{$0} #{$$}: repo #{repo_name} add #{stat[true]} skip #{stat[false]}"
128 if $stdout.tty? or ARGV[0] == '-v'
129 puts "#{$0} #{$$}: repo #{repo_name} add #{stat[true]} skip #{stat[false]}"
134 def self.refresh_repositories
140 def self.repositories
141 return @repositories if @repositories
144 @gitdirbase = Rails.configuration.git_repositories_dir
145 Dir.foreach @gitdirbase do |repo|
146 next if repo.match /^\./
147 git_dir = File.join(@gitdirbase,
148 repo.match(/\.git$/) ? repo : File.join(repo, '.git'))
149 next if git_dir == Rails.configuration.git_internal_dir
150 repo_name = repo.sub(/\.git$/, '')
151 @repositories[repo_name] = {git_dir: git_dir}