#907: update "FileStoreClean" module, some refactoring

This commit is contained in:
Vokhmin Alexey V 2013-02-15 01:49:18 +04:00
parent b7babdef76
commit 7bcbe39e61
6 changed files with 75 additions and 44 deletions

View File

@ -17,10 +17,11 @@ class Projects::Git::TreesController < Projects::Git::BaseController
end end
raise Grit::NoSuchPathError unless @commit raise Grit::NoSuchPathError unless @commit
tag = @project.repo.tags.find{ |t| t.name == @treeish } tag = @project.repo.tags.find{ |t| t.name == @treeish }
if tag sha1 = @project.get_project_tag_sha1(tag, format) if tag
redirect_to "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{@project.get_project_tag_sha1(tag, format)}" if sha1
redirect_to "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}"
else else
archive = @project.create_archive @treeish, format archive = @project.archive_by_treeish_and_format @treeish, format
send_file archive[:path], :disposition => 'attachment', :type => "application/#{format == 'zip' ? 'zip' : 'x-tar-gz'}", :filename => archive[:fullname] send_file archive[:path], :disposition => 'attachment', :type => "application/#{format == 'zip' ? 'zip' : 'x-tar-gz'}", :filename => archive[:fullname]
end end
end end

View File

@ -370,6 +370,10 @@ class BuildList < ActiveRecord::Base
.recent .recent
end end
def sha1_of_file_store_files
packages.pluck(:sha1).compact | (results || []).map{ |r| r['sha1'] }.compact
end
protected protected
def create_container def create_container

View File

@ -130,6 +130,10 @@ class ProductBuildList < ActiveRecord::Base
[BUILD_COMPLETED, BUILD_FAILED, BUILD_CANCELED].include? status [BUILD_COMPLETED, BUILD_FAILED, BUILD_CANCELED].include? status
end end
def sha1_of_file_store_files
(results || []).map{ |r| r['sha1'] }.compact
end
protected protected
def abf_worker_priority def abf_worker_priority

View File

@ -191,32 +191,25 @@ class Project < ActiveRecord::Base
end end
end end
def create_archive(treeish, format)
file_name = "#{name}-#{treeish}"
fullname = "#{file_name}.#{tag_file_format(format)}"
file = Tempfile.new fullname, 'tmp'
system("cd #{path}; git archive --format=#{format == 'zip' ? 'zip' : 'tar'} --prefix=#{file_name}/ #{treeish} #{format == 'zip' ? '' : ' | gzip -9'} > #{file.path}")
file.close
{
:path => file.path,
:fullname => fullname
}
end
def get_project_tag_sha1(tag, format) def get_project_tag_sha1(tag, format)
format_id = ProjectTag::FORMATS["#{tag_file_format(format)}"] format_id = ProjectTag::FORMATS["#{tag_file_format(format)}"]
project_tag = project_tags.where(:tag_name => tag.name, :format_id => format_id).first project_tag = project_tags.where(:tag_name => tag.name, :format_id => format_id).first
return project_tag.sha1 if project_tag && project_tag.commit_id == tag.commit.id return project_tag.sha1 if project_tag && project_tag.commit_id == tag.commit.id && Modules::Models::FileStoreClean.file_exist_on_file_store?(project_tag.sha1)
archive = create_archive(tag.name, format) archive = archive_by_treeish_and_format tag.name, format
sha1 = Digest::SHA1.file(archive[:path]).hexdigest sha1 = Digest::SHA1.file(archive[:path]).hexdigest
unless Modules::Models::FileStoreClean.file_exist_on_file_store? sha1
token = User.find_by_uname('rosa_system').authentication_token token = User.find_by_uname('rosa_system').authentication_token
if %x[ curl #{APP_CONFIG['file_store_url']}/api/v1/file_stores.json?hash=#{sha1} ] == '[]' begin
system "curl --user #{token}: -POST -F 'file_store[file]=@#{archive[:path]};filename=#{name}-#{tag.name}.#{tag_file_format(format)}' #{APP_CONFIG['file_store_url']}/api/v1/upload" resp = JSON `curl --user #{token}: -POST -F 'file_store[file]=@#{archive[:path]};filename=#{name}-#{tag.name}.#{tag_file_format(format)}' #{APP_CONFIG['file_store_url']}/api/v1/upload`
rescue # Dont care about it
resp = {}
end
return nil if resp['sha1_hash'].nil?
end end
if project_tag if project_tag
project_tag.remove_archive_from_file_store(project_tag.sha1) project_tag.destroy_file_from_file_store(project_tag.sha1)
project_tag.update_attributes(:sha1 => sha1) project_tag.update_attributes(:sha1 => sha1)
else else
project_tags.create( project_tags.create(
@ -229,8 +222,24 @@ class Project < ActiveRecord::Base
return sha1 return sha1
end end
def archive_by_treeish_and_format(treeish, format)
@archive ||= create_archive treeish, format
end
protected protected
def create_archive(treeish, format)
file_name = "#{name}-#{treeish}"
fullname = "#{file_name}.#{tag_file_format(format)}"
file = Tempfile.new fullname, 'tmp'
system("cd #{path}; git archive --format=#{format == 'zip' ? 'zip' : 'tar'} --prefix=#{file_name}/ #{treeish} #{format == 'zip' ? '' : ' | gzip -9'} > #{file.path}")
file.close
{
:path => file.path,
:fullname => fullname
}
end
def tag_file_format(format) def tag_file_format(format)
format == 'zip' ? 'zip' : 'tar.gz' format == 'zip' ? 'zip' : 'tar.gz'
end end

View File

@ -1,5 +1,7 @@
# -*- encoding : utf-8 -*- # -*- encoding : utf-8 -*-
class ProjectTag < ActiveRecord::Base class ProjectTag < ActiveRecord::Base
include Modules::Models::FileStoreClean
FORMATS = { FORMATS = {
'zip' => 0, 'zip' => 0,
'tar.gz' => 1 'tar.gz' => 1
@ -16,12 +18,8 @@ class ProjectTag < ActiveRecord::Base
:tag_name, :tag_name,
:format_id :format_id
after_destroy :remove_archive_from_file_store def sha1_of_file_store_files
[sha1]
def remove_archive_from_file_store(sha = sha1)
token = User.find_by_uname('file_store').authentication_token
system "curl --user #{token}: -X DELETE #{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha}.json"
end end
later :remove_archive_from_file_store, :queue => :clone_build
end end

View File

@ -11,17 +11,20 @@ module Modules
end end
later :destroy, :queue => :clone_build later :destroy, :queue => :clone_build
def destroy_files_from_file_store def sha1_of_file_store_files
files = [] raise NotImplementedError, "You should implement this method"
self.results.each {|r| files << r['sha1'] if r['sha1'].present?}
if self.respond_to? :packages
self.packages.each {|pk| files << pk.sha1 if pk.sha1.present?}
end end
if files.count > 0
def destroy_files_from_file_store
sha1_of_file_store_files.each do |sha1|
destroy_file_from_file_store sha1
end
end
def destroy_file_from_file_store(sha1)
token = User.system.find_by_uname('file_store').authentication_token token = User.system.find_by_uname('file_store').authentication_token
uri = URI APP_CONFIG['file_store_url'] uri = URI APP_CONFIG['file_store_url']
Net::HTTP.start(uri.host, uri.port) do |http| Net::HTTP.start(uri.host, uri.port) do |http|
files.each do |sha1|
begin begin
req = Net::HTTP::Delete.new("/api/v1/file_stores/#{sha1}.json") req = Net::HTTP::Delete.new("/api/v1/file_stores/#{sha1}.json")
req.basic_auth token, '' req.basic_auth token, ''
@ -31,8 +34,20 @@ module Modules
end end
end end
end end
end
end def self.file_exist_on_file_store?(sha1)
begin
resp = JSON(RestClient.get "#{APP_CONFIG['file_store_url']}/api/v1/file_stores.json", :params => {:hash => sha1})
rescue # Dont care about it
resp = []
end
if resp[0].respond_to?('[]') && resp[0]['file_name'] && resp[0]['sha1_hash']
true
else
false
end
end
end end
end end
end end