# encoding: utf-8 #-- # Copyright (C) 2010 Juho Nieminen # Copyright (C) 2010 Tero Hänninen # Copyright (C) 2010 Marko Peltola # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) # Copyright (C) 2007, 2008 Johan Sørensen # Copyright (C) 2008 David A. Cuadrado # Copyright (C) 2008 Tor Arne Vestbø # Copyright (C) 2009 Fabio Akita # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . #++ include GrmfHelper class RepositoriesController < ApplicationController include FilenameSanitizer before_filter :login_required, :except => [:index, :show, :writable_by, :config, :search_clones] before_filter :find_repository_owner before_filter :require_owner_adminship, :only => [:new, :create] before_filter :find_and_require_repository_adminship, :only => [:edit, :update, :confirm_delete, :destroy] before_filter :find_and_require_repository_committership, :only => [:update_repo_with_zip] before_filter :find_and_require_repository_view_right, :except => [:index, :create, :new, :destroy, :config, :writable_by] before_filter :require_user_has_ssh_keys, :only => [:clone, :create_clone] before_filter :only_projects_can_add_new_repositories, :only => [:new, :create] skip_before_filter :public_and_logged_in, :only => [:writable_by, :config] renders_in_site_specific_context :except => [:writable_by, :config] # Currently there aren't any links to this page so just hide every repo at least for now def index if term = params[:filter] @repositories = []#@project.search_repositories(term) else @repositories = []#@owner.repositories.find(:all, :include => [:user, :events, :project]) end respond_to do |wants| wants.html wants.xml {render :xml => @repositories.to_xml} wants.json {render :json => to_json(@repositories)} end end def show @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) @root = @repository @events = @repository.events.top.paginate(:all, :page => params[:page], :order => "created_at desc") @atom_auto_discovery_url = repo_owner_path(@repository, :project_repository_path, @repository.project, @repository, :format => :atom) response.headers['Refresh'] = "5" unless @repository.ready respond_to do |format| format.html format.xml { render :xml => @repository } format.atom { } end end def new @repository = @project.repositories.new @root = Breadcrumb::NewRepository.new(@project) @repository.kind = Repository::KIND_PROJECT_REPO @repository.owner = @project.owner @repository.mirror_url = "http://" if @project.repositories.mainlines.count == 0 @repository.name = "mainline" end @projects = current_user.administrated_projects.find(:all, :order => "created_at desc") end def create @projects = current_user.administrated_projects.find(:all, :order => "created_at desc") @project = current_user.projects.find_by_title(params[:repo_in_project]) @repository = @project.repositories.new(params[:repository]) @root = Breadcrumb::NewRepository.new(@project) @repository.kind = Repository::KIND_PROJECT_REPO @repository.owner = @project.owner @repository.user = current_user set_mirroring_options(@repository, params[:mirroring]) unless params[:local_package_file].blank? package_file = params[:local_package_file] zip_dir = Repository.dir_for_temp_zip(@repository.real_gitdir) `mkdir #{zip_dir}` path = File.join(zip_dir, "init.zip") File.open(path, "wb") { |f| f.write(package_file.read) } end if @repository.save flash[:success] = I18n.t("repositories_controller.create_success") redirect_to [@repository.project_or_owner, @repository] else render :action => "new" end end undef_method :clone def clone @repository_to_clone = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) @root = Breadcrumb::CloneRepository.new(@repository_to_clone) unless @repository_to_clone.has_commits? flash[:error] = I18n.t "repositories_controller.new_clone_error" redirect_to [@owner, @repository_to_clone] return end @repository = Repository.new_by_cloning(@repository_to_clone, current_user.login) end def create_clone @repository_to_clone = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) @root = Breadcrumb::CloneRepository.new(@repository_to_clone) unless @repository_to_clone.has_commits? respond_to do |format| format.html do flash[:error] = I18n.t "repositories_controller.create_clone_error" redirect_to [@owner, @repository_to_clone] end format.xml do render :text => I18n.t("repositories_controller.create_clone_error"), :location => [@owner, @repository_to_clone], :status => :unprocessable_entity end end return end @repository = Repository.new_by_cloning(@repository_to_clone) @repository.name = params[:repository][:name] @repository.user = current_user case params[:repository][:owner_type] when "User" @repository.owner = current_user @repository.kind = Repository::KIND_USER_REPO when "Group" @repository.owner = current_user.groups.find(params[:repository][:owner_id]) @repository.kind = Repository::KIND_TEAM_REPO end respond_to do |format| if @repository.save @owner.create_event(Action::CLONE_REPOSITORY, @repository, current_user, @repository_to_clone.id) location = repo_owner_path(@repository, :project_repository_path, @owner, @repository) format.html { redirect_to location } format.xml { render :xml => @repository, :status => :created, :location => location } else format.html { render :action => "clone" } format.xml { render :xml => @repository.errors, :status => :unprocessable_entity } end end end def update_repo_with_zip_form @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) end def update_repo_with_zip @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) @root = Breadcrumb::UpdateRepositoryWithZip.new(@repository) target_head = "" if params[:target_head_selector] == "" target_head = params[:target_head] else target_head = params[:target_head_selector] end if !params[:local_package_file].blank? package_file = params[:local_package_file] temp_dir = Repository.dir_for_temp_zip(@repository.real_gitdir) `mkdir #{temp_dir}` file_path = File.join(temp_dir, sanitize_filename(package_file.original_filename)) File.open(file_path, "wb") { |f| f.write(package_file.read) } Repository.update_contents_from_zip(@repository.real_gitdir, file_path, {"source_type" => "local_file", "target_branch" => target_head}) #@repository.project.create_push_event(@repository, target_head, current_user) # FIXME redirect_to [@repository.project_or_owner, @repository] elsif !params[:package_url].blank? Repository.update_contents_from_zip(@repository.real_gitdir, params[:package_url], {"source_type" => "url", "target_branch" => target_head}) #@repository.project.create_push_event(@repository, target_head, current_user) # FIXME redirect_to [@repository.project_or_owner, @repository] else render :action => "update_repo_with_zip_form" end end def edit @root = Breadcrumb::EditRepository.new(@repository) @groups = current_user.groups @heads = @repository.git.heads end def search_clones @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) @repositories = @repository.search_clones(params[:filter]) render :json => to_json(@repositories) end def update @root = Breadcrumb::EditRepository.new(@repository) @groups = current_user.groups @heads = @repository.git.heads Repository.transaction do unless params[:repository][:owner_id].blank? @repository.change_owner_to!(current_user.groups.find(params[:repository][:owner_id])) end @repository.head = params[:repository][:head] @repository.log_changes_with_user(current_user) do @repository.replace_value(:name, params[:repository][:name]) @repository.replace_value(:description, params[:repository][:description], true) end @repository.private_repo = params[:repository][:private_repo] @repository.deny_force_pushing = params[:repository][:deny_force_pushing] @repository.notify_committers_on_new_merge_request = params[:repository][:notify_committers_on_new_merge_request] @repository.merge_requests_enabled = params[:repository][:merge_requests_enabled] @repository.mirror_url = params[:repository][:mirror_url] @repository.license = params[:repository][:license] set_mirroring_options(@repository, params[:mirroring]) @repository.save! GrmfHelper::update_metainfo_to_repository(@repository) flash[:success] = "Repository updated" redirect_to [@repository.project_or_owner, @repository] end rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound render :action => "edit" end # Used internally to check write permissions by gitorious def writable_by @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) user = User.find_by_login(params[:username]) if user && result = /^refs\/merge-requests\/(\d+)$/.match(params[:git_path].to_s) # git_path is a merge request begin if merge_request = @repository.merge_requests.find_by_sequence_number!(result[1]) and (merge_request.user == user) render :text => "true" and return end rescue ActiveRecord::RecordNotFound # No such merge request end elsif user && user.can_write_to?(@repository) render :text => "true" and return end render :text => 'false' and return end def config @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) config_data = "real_path:#{@repository.real_gitdir}\n" config_data << "force_pushing_denied:" config_data << (@repository.deny_force_pushing? ? 'true' : 'false') render :text => config_data end def confirm_delete @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) unless @repository.can_be_deleted_by?(current_user) flash[:error] = I18n.t "repositories_controller.adminship_error" redirect_to(@owner) and return end end def destroy @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) if @repository.can_be_deleted_by?(current_user) repo_name = @repository.name flash[:notice] = I18n.t "repositories_controller.destroy_notice" @repository.destroy @repository.project.create_event(Action::DELETE_REPOSITORY, @owner, current_user, repo_name) else flash[:error] = I18n.t "repositories_controller.destroy_error" end redirect_to @owner end private def require_owner_adminship unless @owner.admin?(current_user) respond_denied_and_redirect_to(@owner) return end end def find_and_require_repository_adminship @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) unless @repository.admin?(current_user) respond_denied_and_redirect_to(repo_owner_path(@repository, :project_repository_path, @owner, @repository)) return end end def find_and_require_repository_committership @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) unless @repository.committer?(current_user) respond_denied_and_redirect_to(repo_owner_path(@repository, :project_repository_path, @owner, @repository)) return end end def find_and_require_repository_view_right @repository = @owner.repositories.find_by_name_in_project!(params[:id], @containing_project) unless @repository.can_be_viewed_by?(current_user, logged_in?) flash[:error] = I18n.t "application.require_current_user" redirect_to root_path return end end def respond_denied_and_redirect_to(target) respond_to do |format| format.html { flash[:error] = I18n.t "repositories_controller.adminship_error" redirect_to(target) } format.xml { render :text => I18n.t( "repositories_controller.adminship_error"), :status => :forbidden } end end def to_json(repositories) repositories.map { |repo| { :name => repo.name, :description => repo.description, :uri => url_for(project_repository_path(@project, repo)), :img => repo.owner.avatar? ? repo.owner.avatar.url(:thumb) : "/images/default_face.gif", :owner => repo.owner.title, :owner_type => repo.owner_type.downcase, :owner_uri => url_for(repo.owner) } }.to_json end def only_projects_can_add_new_repositories if !@owner.is_a?(Project) respond_to do |format| format.html { flash[:error] = I18n.t("repositories_controller.only_projects_create_new_error") redirect_to(@owner) } format.xml { render :text => I18n.t( "repositories_controller.only_projects_create_new_error"), :status => :forbidden } end return end end def set_mirroring_options(repo, option) if option == "svn_mirror" repo.kind = Repository::KIND_SVN_MIRROR elsif option == "zip_mirror" repo.kind = Repository::KIND_ZIP_MIRROR else repo.kind = Repository::KIND_PROJECT_REPO repo.mirror_url = "" end end end