diff --git a/.gitignore b/.gitignore index a01ee289f..9e6dc21ef 100755 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .*.swp +.AppleDouble diff --git a/Gemfile b/Gemfile index 7d87e7a5a..4d483df2e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,6 @@ -source :rubygems -gem "inifile", "~>0.4.1" -gem "lockfile", "~>1.4.3" -gem "net-ssh", "~>2.1.4" +source 'https://rubygems.org' +gem 'inifile', '~>0.4.1' +gem 'lockfile', '~>1.4.3' +gem 'net-ssh', '~>2.1.4' +gem 'delayed_job', '=2.0.4' + diff --git a/README.mkd b/README.mkd index 945b9cf82..6f8c0b31b 100755 --- a/README.mkd +++ b/README.mkd @@ -1,3 +1,8 @@ +# Redmine Git Hosting Plugin with Delayed Jobs (v0.5.0) + +Added support for delayed_jobs ACL update and improved visualization of access rights. +-- Tomas Srna + # Redmine Git Hosting Plugin (v0.4.2) A ChiliProject / Redmine plugin which makes configuring your own git hosting easy. This plugin allows straightforward management diff --git a/Rakefile b/Rakefile index 57de66cb6..510d4ef4e 100644 --- a/Rakefile +++ b/Rakefile @@ -3,5 +3,12 @@ begin require 'lockfile' require 'net/ssh' rescue - puts "need to install tmpdir lockfile and net/ssh gems" + puts 'need to install tmpdir lockfile and net/ssh gems' +end + +begin + gem 'delayed_job', '~>2.0.4' + require 'delayed/tasks' +rescue LoadError + STDERR.puts 'Run `rake gems:install` to install delayed_job' end diff --git a/app/controllers/git_http_controller.rb b/app/controllers/git_http_controller.rb index b5faaba1a..bf2d41fcf 100644 --- a/app/controllers/git_http_controller.rb +++ b/app/controllers/git_http_controller.rb @@ -10,7 +10,6 @@ class GitHttpController < ApplicationController before_filter :authenticate - def index p1 = params[:p1] p2 = params[:p2] @@ -241,7 +240,7 @@ def update_server_info end def git_command(command) - return "#{run_git_prefix()} env GL_BYPASS_UPDATE_HOOK=true git #{command} '" + return "#{run_git_prefix()} GL_BYPASS_UPDATE_HOOK=true GL_LIBDIR=\"/etc/perl\" git #{command} '" end diff --git a/app/controllers/gitolite_hooks_controller.rb b/app/controllers/gitolite_hooks_controller.rb index 21461a7bc..9d4b47234 100644 --- a/app/controllers/gitolite_hooks_controller.rb +++ b/app/controllers/gitolite_hooks_controller.rb @@ -46,48 +46,6 @@ def post_receive output.write(result) output.flush } if @project.repository_mirrors.any? - - # Notify CIA - #Thread.abort_on_exception = true - Thread.new(@project, params[:refs]) {|project, refs| - GitHosting.logger.debug "Notifying CIA" - output.write("Notifying CIA\n") - output.flush - #GitHosting.logger.debug "REFS #{refs}" - - refs.each {|ref| - oldhead, newhead, refname = ref.split(',') - - # Only pay attention to branch updates - next if not refname.match(/refs\/heads\//) - - branch = refname.gsub('refs/heads/', '') - - if newhead.match(/^0{40}$/) - # Deleting a branch - GitHosting.logger.debug "Deleting branch \"#{branch}\"" - next - elsif oldhead.match(/^0{40}$/) - # Creating a branch - GitHosting.logger.debug "Creating branch \"#{branch}\"" - range = newhead - else - range = "#{oldhead}..#{newhead}" - end - - revisions = %x[#{GitHosting.git_exec} --git-dir='#{GitHosting.repository_path(@project)}' rev-list --reverse #{range}] - #GitHosting.logger.debug "Revisions in Range: #{revisions.split().join(' ')}" - - revisions.split().each{|rev| - revision = project.repository.find_changeset_by_name(rev.strip) - #GitHosting.logger.debug "Revision Found: #{revision.revision}" - next if project.repository.cia_notifications.notified?(revision) # Already notified about this commit - GitHosting.logger.info "Notifying CIA: Branch => #{branch} REVISION => #{revision.revision}" - CiaNotificationMailer.deliver_notification(revision, branch) - project.repository.cia_notifications.notified(revision) - } - } - } if !params[:refs].nil? && @project.repository.extra.notify_cia==1 }, :layout => false end diff --git a/app/controllers/gitolite_public_keys_controller.rb b/app/controllers/gitolite_public_keys_controller.rb index e11721d2b..ed989ab60 100644 --- a/app/controllers/gitolite_public_keys_controller.rb +++ b/app/controllers/gitolite_public_keys_controller.rb @@ -29,7 +29,10 @@ def create if @gitolite_public_key.save flash[:notice] = l(:notice_public_key_added) else - @gitolite_public_key = GitolitePublicKey.new(:user => @user) + #@gitolite_public_key = GitolitePublicKey.new(:user => @user) + @gitolite_public_key.errors.each do |attr, message| + flash[:error] = "#{attr}: #{message}" if flash[:error].blank? + end end redirect_to url_for(:controller => 'my', :action => 'account') end diff --git a/app/models/cia_notification_mailer.rb b/app/models/cia_notification_mailer.rb index eb763b85c..24f2b4fe9 100644 --- a/app/models/cia_notification_mailer.rb +++ b/app/models/cia_notification_mailer.rb @@ -34,7 +34,7 @@ def deliver!(mail = @mail) begin ok, result = rpc_server.call2("hub.deliver", @body) - if ok: + if ok GitHosting.logger.info "RPC Called. OK => #{ok} Result => #{result}" return false end diff --git a/app/models/git_hosting_observer.rb b/app/models/git_hosting_observer.rb index 8b8de5462..89e1dc354 100644 --- a/app/models/git_hosting_observer.rb +++ b/app/models/git_hosting_observer.rb @@ -49,6 +49,7 @@ def before_save(object) def after_save(object) + GitHosting.logger.debug "On GitHostingObserver.after_save for #{object.class} #{object.id}" update_repositories(object) end @@ -63,22 +64,41 @@ def after_destroy(object) protected - def update_repositories(object) - + def update_repositories(object) projects = [] case object when Repository::Git then projects.push(object.project) when User then projects = object.projects unless is_login_save?(object) when GitolitePublicKey then projects = object.user.projects when Member then projects.push(object.project) - when Role then projects = object.members.map(&:project).flatten.uniq.compact + when Role then projects = object.members.map(&:project).flatten.uniq.compact + when Project then projects.push(object) end + + projects.select! do |p| + p if (!p.repository.nil? && p.repository.is_a?(Repository::Git) && + !p.repository.update_requested.nil? && !p.repository.update_finished.nil? && + p.repository.update_requested < p.repository.update_finished) + end + if(projects.length > 0) if (@@updating_active) - GitHosting::update_repositories(projects, false) - else - @@cached_project_updates.concat(projects) - end + #GitHosting::update_repositories(projects, false) + project_pids = projects.collect {|p| p.id} + projects.each do |p| + unless p.repository.nil? + p.repository.update_requested = Time.new + ua = @@updating_active + @@updating_active = false + p.repository.save + @@updating_active = ua + end + end + GitHosting.logger.debug 'Calling delayed update_repositories_pid' + GitHosting.delay.update_repositories_pid(project_pids, false) + else + @@cached_project_updates.concat(projects) + end end end diff --git a/app/models/git_hosting_settings_observer.rb b/app/models/git_hosting_settings_observer.rb index fee8d8a3f..6d465ddaa 100644 --- a/app/models/git_hosting_settings_observer.rb +++ b/app/models/git_hosting_settings_observer.rb @@ -27,7 +27,7 @@ def after_save(object) all_projects.each do |p| if p.repository.is_a?(Repository::Git) r = p.repository - repo_name= p.parent ? File.join(GitHosting::get_full_parent_path(p, true),p.identifier) : p.identifier + repo_name = p.identifier r.url = File.join(object.value['gitRepositoryBasePath'], "#{repo_name}.git") r.root_url = r.url r.save diff --git a/app/models/gitolite_public_key.rb b/app/models/gitolite_public_key.rb index 1c36e36e1..dce427b82 100755 --- a/app/models/gitolite_public_key.rb +++ b/app/models/gitolite_public_key.rb @@ -11,6 +11,7 @@ class GitolitePublicKey < ActiveRecord::Base named_scope :inactive, {:conditions => {:active => GitolitePublicKey::STATUS_LOCKED}} validate :has_not_been_changed + validate :fingerprintable_key before_validation :set_identifier @@ -31,5 +32,19 @@ def set_identifier self.identifier ||= "redmine_#{self.user.login.underscore}_#{Time.now.to_i.to_s}_#{Time.now.usec.to_s}".gsub(/[^0-9a-zA-Z\-]/,'_') end + def fingerprintable_key + return true unless key # Don't test if there is no key. + file = Tempfile.new('key_file') + begin + file.puts key + file.rewind + fingerprint_output = `ssh-keygen -lf #{file.path} 2>&1` # Catch stderr. + ensure + file.close + file.unlink # deletes the temp file + end + errors.add(:key, "can't be fingerprinted - not a public key") if fingerprint_output.match("is not a public key file") + end + def to_s ; title ; end end diff --git a/app/views/my/account.rhtml b/app/views/my/account.rhtml index e81ee0cdc..486fadabb 100644 --- a/app/views/my/account.rhtml +++ b/app/views/my/account.rhtml @@ -45,11 +45,10 @@ <% if @gitolite_public_keys.any? %> - + <% else %> - + <% end %> - <% @gitolite_public_keys.each do |key| %> diff --git a/app/views/projects/_git_urls.erb b/app/views/projects/_git_urls.erb index be2121e58..7aae08e70 100644 --- a/app/views/projects/_git_urls.erb +++ b/app/views/projects/_git_urls.erb @@ -1,53 +1,64 @@ <% if @project.repository && @project.repository.is_a?(Repository::Git) %> <% content_for :header_tags do %> - <%= stylesheet_link_tag('git_url_display', :plugin => 'redmine_git_hosting') %> - <%= javascript_include_tag('git_url_display', :plugin => 'redmine_git_hosting') %> - - <%= stylesheet_link_tag('zero_clipboard', :plugin => 'redmine_git_hosting') %> - <%= javascript_include_tag('ZeroClipboard', :plugin => 'redmine_git_hosting') %> - <%= javascript_include_tag('zero_clipboard_setup', :plugin => 'redmine_git_hosting') %> - - - + <%= stylesheet_link_tag('git_url_display', :plugin => 'redmine_git_hosting') %> + <%= javascript_include_tag('git_url_display', :plugin => 'redmine_git_hosting') %> + + <%= stylesheet_link_tag('zero_clipboard', :plugin => 'redmine_git_hosting') %> + <%= javascript_include_tag('ZeroClipboard', :plugin => 'redmine_git_hosting') %> + <%= javascript_include_tag('zero_clipboard_setup', :plugin => 'redmine_git_hosting') %> + + + <% end %> <% if (project.module_enabled?(:repository) && Setting.plugin_redmine_git_hosting['gitRepositoriesShowUrl'].to_s != "false" ) && ((!User.current.anonymous?) || project.repository.extra[:git_http].to_s != "0" || (project.is_public && project.repository.extra[:git_daemon].to_s != "0" )) %> -
+

Git Repository

-
-
    - <% if !User.current.anonymous? %> -
  • SSH
  • - <% end %> - <% if project.repository.extra[:git_http].to_s != "0" %> -
  • HTTP
  • - <% end %> - <% if project.is_public && project.repository.extra[:git_daemon].to_s != "0" %> -
  • Git
  • - <% end %> -
- - - This URL has Read-Only access. -
+ <% + pc = 0 + User.current.gitolite_public_keys.each { |p| pc = pc+1 if p.active == true } + flash.now[:warning] = l(:no_public_key) if pc < 1 + + + if !@project.repository.blank? && !@project.repository.update_requested.blank? && + (@project.repository.update_finished.blank? || + @project.repository.update_requested > @project.repository.update_finished) + flash.now[:warning] = l(:update_pending) + @project.repository.update_requested.to_s + end +%> +
+
    + <% if !User.current.anonymous? && project.members.find_by_user_id(User.current.id) != nil %> +
  • SSH
  • + <% end %> + <% if project.is_public %> +
  • <%=l(:http_anon)%>
  • + <% else %> +
  • <%=l(:http_auth)%>
  • + <% end %> +
+ + + <%= l(:this_url_has) %> Read-Only <%= l(:access) %>. +
<% end %> <% end %> diff --git a/app/views/projects/settings/_repository.rhtml b/app/views/projects/settings/_repository.rhtml index 7d85bd959..8d959f11c 100644 --- a/app/views/projects/settings/_repository.rhtml +++ b/app/views/projects/settings/_repository.rhtml @@ -61,23 +61,12 @@ end end %> -

- <%= label_tag "extra[git_daemon]", l(:field_git_daemon) %> - <%= select_tag "extra[git_daemon]", options_for_select([ [l(:label_disabled), "0"], [l(:label_enabled), "1"]], :selected=>extra_vals[:git_daemon]) %> -

<%= label_tag "extra[git_http]", l(:field_git_http) %> - <%= select_tag "extra[git_http]", options_for_select([ [l(:label_disabled), "0"], [l(:label_https_only), "1"], [l(:label_https_and_http), "2"] ], :selected=>extra_vals[:git_http]) %> -

-

- <%= label_tag "extra[notify_cia]", l(:field_notify_cia) %> - <%= select_tag "extra[notify_cia]", options_for_select([ [l(:label_disabled), "0"], [l(:label_enabled), "1"]], :selected=>extra_vals[:notify_cia]) %> - <% if extra_vals[:notify_cia] == "1" %> - "test", :projectid => @repository.project.identifier) %>"><%= l(:field_notify_cia_test) %> - - <% end %> + <%= select_tag "extra[git_http]", options_for_select([ [l(:label_disabled), "0"], [l(:label_https_only), "1"] + #, [l(:label_https_and_http), "2"] + ], :selected=>extra_vals[:git_http]) %>

- <%= javascript_include_tag('notify_cia_test', :plugin => 'redmine_git_hosting') %>
<% else %> <%= repository_field_tags(f, @repository) if @repository %> diff --git a/app/views/repositories/_git_urls.erb b/app/views/repositories/_git_urls.erb index 2bc194b0b..5ea11aa8b 100644 --- a/app/views/repositories/_git_urls.erb +++ b/app/views/repositories/_git_urls.erb @@ -11,7 +11,7 @@ <% end %> + <% + pc = 0 + User.current.gitolite_public_keys.each { |p| pc = pc+1 if p.active == true } + flash.now[:warning] = l(:no_public_key) if pc < 1 + + if !@project.repository.blank? && !@project.repository.update_requested.blank? && + (@project.repository.update_finished.blank? || + @project.repository.update_requested > @project.repository.update_finished) + flash.now[:warning] = l(:update_pending) + @project.repository.update_requested.to_s + end +%> + <% if (!User.current.anonymous?) || project.repository.extra[:git_http].to_s != "0" || (project.is_public && project.repository.extra[:git_daemon].to_s != "0" ) %>
- This URL has Read-Only access. + <%= l(:this_url_has) %> Read-Only <%= l(:access) %>.

<% end %> diff --git a/app/views/repositories/git_instructions.html.erb b/app/views/repositories/git_instructions.html.erb index 7ec4075eb..751423aa6 100644 --- a/app/views/repositories/git_instructions.html.erb +++ b/app/views/repositories/git_instructions.html.erb @@ -2,6 +2,14 @@ <% flash.now[:warning] = "Repository is empty. Get started by following the instructions below." %> <% git_ssh_url = Setting.plugin_redmine_git_hosting['gitUser'] + "@" + Setting.plugin_redmine_git_hosting['gitServer'] + ":" + GitHosting.repository_name(@project) + '.git' %> +<% + if !@project.repository.blank? && !@project.repository.update_requested.blank? && + (@project.repository.update_finished.blank? || + @project.repository.update_requested > @project.repository.update_finished) + flash.now[:warning] = l(:update_pending) + @project.repository.update_requested.to_s + end +%> +

Git Setup:

diff --git a/app/views/settings/_redmine_git_hosting.html.erb b/app/views/settings/_redmine_git_hosting.html.erb index c6b1e7760..2e8773f38 100644 --- a/app/views/settings/_redmine_git_hosting.html.erb +++ b/app/views/settings/_redmine_git_hosting.html.erb @@ -1,5 +1,10 @@
+

+ + <%= select_tag("settings[gitLogLevel]", options_for_select([['debug', '0'], ['info', '1'], ['warn', '2'], ['error', '3'], ['fatal', '4']], @settings['gitLogLevel'])) %> +
+

<%= select_tag("settings[allProjectsUseGit]", options_for_select([[l(:label_enabled), 'true'], [l(:label_disabled), 'false']], @settings['allProjectsUseGit'])) %> @@ -48,7 +53,6 @@

-

<%= l(:label_git_cache_parameters)%>

diff --git a/assets/javascripts/git_url_display.js b/assets/javascripts/git_url_display.js index b78baa211..57677455c 100644 --- a/assets/javascripts/git_url_display.js +++ b/assets/javascripts/git_url_display.js @@ -1,13 +1,12 @@ -var allGitUrlIds = ["git_url_ssh", "git_url_http", "git_url_git"] +var allGitUrlIds = ["git_url_ssh", "git_url_http"] function updateGitUrl(el) { guHttpBase = guHttpBase.replace(/\/$/, "") var urls=[] urls["git_url_ssh"] = [guGitUser + "@" + guGitServer + ":" + guProjectName, guUserIsCommitter] - urls["git_url_http"] = [guHttpProto + "://" + ( (!guProjectIsPublic) || guUserIsCommitter ? guUser + "@" : "") + guHttpBase + "/" + guProjectName, guUserIsCommitter] - urls["git_url_git"] = ["git://" + guGitServer + "/" + guProjectName, false] - var allGitUrlIds = ["git_url_ssh", "git_url_http", "git_url_git"] + urls["git_url_http"] = [guHttpProto + "://" + guHttpBase + "/" + guProjectName, guUserIsCommitter && !guProjectIsPublic] + var allGitUrlIds = ["git_url_ssh", "git_url_http"] var selected_id = el.id document.getElementById("git_url_text").value = urls[selected_id][0]; diff --git a/assets/stylesheets/git_url_display.css b/assets/stylesheets/git_url_display.css index dbe448150..eb879d542 100644 --- a/assets/stylesheets/git_url_display.css +++ b/assets/stylesheets/git_url_display.css @@ -1,7 +1,7 @@ #git_url_box { - height: 75px; + height: 30px; padding: 10px 0 0; margin:0px; } diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 2ce8a4693..71ffb9b68 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -1,75 +1,76 @@ -'en': - label_all_git: Automatically Initialize Git Repositories For New Projects - label_delete_git_repositories: Delete Git Repository When Project is Deleted - label_git_server: Gitolite Server Domain - label_http_server: HTTP Server Domain (for git http urls) - label_git_user: Git Username - label_gitolite_identity_public_key_file: Gitolite SSH Identity File (Public Key) - label_gitolite_identity_file: Gitolite SSH Identity File (Private Key) +'cs': + label_log_level: Úroveň logování + label_all_git: Automaticky inicializovat úložiště pro nové projekty + label_delete_git_repositories: Smazat Git úložiště při smazání projektu + label_git_server: Doména Gitolite Serveru + label_http_server: Doména HTTP Serveru (pro HTTP Git) + label_git_user: Git uživatel + label_gitolite_identity_public_key_file: Gitolite SSH Identity File (veřejný klíč) + label_gitolite_identity_file: Gitolite SSH Identity File (privátní klíč) label_git_repository_base_path: Git Repository Base Path (Relative to git user home) field_git_daemon: Git Daemon field_git_http: Git Smart HTTP - field_notify_cia: Notify CIA.vc + field_notify_cia: Notifikace CIA.vc - label_git_show_urls: "Show checkout URL's" - label_enabled: Enabled - label_disabled: Disabled - label_https_only: HTTPS Only - label_https_and_http: HTTPS and HTTP + label_git_show_urls: "Zobrazit checkout URL" + label_enabled: Povoleno + label_disabled: Zakázáno + label_https_only: Pouze HTTPS + label_https_and_http: HTTPS a HTTP - label_permissions_header: Required Permissions - label_sudo_web_to_git_user: Web user is able to sudo to Git user? - label_sudo_git_to_web_user: Git user is able to sudo to Web user? + label_permissions_header: Potrebná oprávnění + label_sudo_web_to_git_user: Web uživatel může sudo na Git uživatele? + label_sudo_git_to_web_user: Git uživatel může sudo na Web uživatele? - label_copy_to_clipboard: "Copy to clipboard" + label_copy_to_clipboard: "Kopírovat do schránky" label_git_hook_header: Repository Hooks - label_git_hook_debug: Run hooks in Debug mode - label_git_hooks_are_asynchronous: Run hooks asynchronously - label_hook_installed: Hook installed - - label_public_keys: Public keys - label_public_key_new: New public key - field_public_key: Key - notice_public_key_updated: Public key was successfully updated. - notice_public_key_added: Public key was successfully added. - label_key_cannot_be_changed_please_create_new_key: 'The key cannot be altered anymore. However, you can deactivate it and create a new one.' + label_git_hook_debug: Spouštět hooks v Debug módu + label_git_hooks_are_asynchronous: Spouštět hooks asynchronně + label_hook_installed: Hook nainstalován + + label_public_keys: Veřejné klíče + label_public_key_new: Nový veřejný klíč + field_public_key: Klíč + notice_public_key_updated: Veřejný klíč byl aktualizován. + notice_public_key_added: Veřejný klíč byl úspěšně přidán. + label_key_cannot_be_changed_please_create_new_key: 'Klíč není možné měnit. Můžete ho ale deaktivovat a přidat nový.' activerecord: errors: messages: - 'may not be changed': 'may not be changed' + 'may not be changed': 'se nedá měnit' label_git_cache_max_time: Max Cache Time label_git_cache_max_elements: Max Cache Elements label_git_cache_max_size: Max Cache Element Size label_git_cache_parameters: Git Cache Parameters - label_no_public_keys: No Public Keys Defined + label_no_public_keys: Žádné veřejné klíče - project_not_found: 'No project was found with the identifier "%{identifier}"' + project_not_found: 'Žádný projekt s identifikátorem "%{identifier}"' cia_not_enough_permissions: You don't have the required permissions to test CIA.vc notifications. field_notify_cia_test: Test Notification cia_notification_ok: Notification to CIA.vc sent. - label_update_all_hooks: Update ALL repositories hook settings + label_update_all_hooks: Aktualizovat hooks pro všechny projekty - field_private_key: Private Key - field_private_key_warning: "Do not use your own Private Key!
Please generate a new one and upload it to the mirror server." - label_mirror_create: Create Repository Mirror - label_mirror_delete: Delete Repository Mirror - label_mirror_edit: Edit Repository Mirror - mirror_notice_deleted: Mirror was successfully deleted - mirror_notice_created: Mirror was successfully created - mirror_notice_updated: Mirror was successfully updated - mirror_notice_create_failed: Failed to create mirror + field_private_key: Soukromý klíč + field_private_key_warning: "Nepoužívejte soukromý klíč!
Vygenerujte nový a použijte ho na mirror server." + label_mirror_create: Vytvořit mirror úložiště + label_mirror_delete: Smazat mirror úložiště + label_mirror_edit: Upravit mirror úložiště + mirror_notice_deleted: Mirror byl úspěšně smazán + mirror_notice_created: Mirror byl úspěšně vytvořen + mirror_notice_updated: Mirror byl úspěšně aktualizován + mirror_notice_create_failed: Nepodařilo se vytvořit mirror button_push: Push button_push_title: "Push To Mirror" @@ -77,3 +78,12 @@ mirror_push_output_label: 'Output:' mirror_push_sucess: Success. mirror_push_fail: Failed! + + this_url_has: 'Tato adresa má' + access: 'oprávnění' + no_public_key: "Nemáte veřejný klíč v profilu. SSH protokol nebude fungovat." + update_pending: "Oprávnění pro úložiště jsou právě aktualizována. Aktualizace žádána: " + http_auth: 'HTTP Autentifikované' + http_anon: 'HTTP Anonymní' + + label_repo_flat_path: 'Přímá cesta úložiště (bez rodičovských úložišť v cestě)' \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index 2ce8a4693..4f971c4c6 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,5 @@ 'en': + log_level: Log Level label_all_git: Automatically Initialize Git Repositories For New Projects label_delete_git_repositories: Delete Git Repository When Project is Deleted label_git_server: Gitolite Server Domain @@ -77,3 +78,12 @@ mirror_push_output_label: 'Output:' mirror_push_sucess: Success. mirror_push_fail: Failed! + + this_url_has: 'This URL has' + acccess: 'access' + no_public_key: "You have no public key in your profile. SSH protocol will not work." + update_pending: "Repository access control is being updated. Update requested: " + http_auth: 'HTTP Authenticated' + http_anon: 'HTTP Anonymous' + + label_repo_flat_path: 'Flat repository path (without parent projects in path)' diff --git a/db/migrate/2011081300000_create_git_repository_extras.rb b/db/migrate/2011081300000_create_git_repository_extras.rb index 7db885fde..bca8a3efe 100644 --- a/db/migrate/2011081300000_create_git_repository_extras.rb +++ b/db/migrate/2011081300000_create_git_repository_extras.rb @@ -33,7 +33,7 @@ def self.up #update repo url to match location of gitolite repos r = project.repository - repo_name= project.parent ? File.join(GitHosting::get_full_parent_path(project, true),project.identifier) : project.identifier + repo_name = project.identifier r.url = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'], "#{repo_name}.git") r.root_url = r.url r.extra = e diff --git a/db/migrate/20130328000000_repository_update_time.rb b/db/migrate/20130328000000_repository_update_time.rb new file mode 100644 index 000000000..144c8e9df --- /dev/null +++ b/db/migrate/20130328000000_repository_update_time.rb @@ -0,0 +1,12 @@ +#-- encoding: UTF-8 + +class RepositoryUpdateTime < ActiveRecord::Migration + def self.up + add_column :repositories, :update_requested, :datetime + add_column :repositories, :update_finished, :datetime + end + def self.down + remove_column :repositories, :update_requested + remove_column :repositories, :update_finished + end +end diff --git a/init.rb b/init.rb index 5567c40f2..e34025ace 100755 --- a/init.rb +++ b/init.rb @@ -7,18 +7,18 @@ require File.join(File.dirname(__FILE__), 'app', 'models', 'git_cia_notification') Redmine::Plugin.register :redmine_git_hosting do - name 'Redmine Git Hosting Plugin' - author 'Eric Bishop, Pedro Algarvio, Christian Käser, Zsolt Parragi, Yunsang Choi, Joshua Hogendorn, Jan Schulz-Hofen and others' + name 'Redmine Git Hosting Plugin with Delayed Jobs' + author 'Eric Bishop, Pedro Algarvio, Christian Käser, Zsolt Parragi, Yunsang Choi, Joshua Hogendorn, Jan Schulz-Hofen and Tomas Srna' description 'Enables Redmine / ChiliProject to control hosting of git repositories' - version '0.4.2' - url 'https://github.com/ericpaulbishop/redmine_git_hosting' + version '0.5.1' + url 'https://github.com/srna/redmine_git_hosting' settings :default => { 'httpServer' => 'localhost', 'gitServer' => 'localhost', 'gitUser' => 'git', 'gitRepositoryBasePath' => 'repositories/', - 'gitoliteIdentityFile' => RAILS_ROOT + '/.ssh/gitolite_admin_id_rsa', - 'gitoliteIdentityPublicKeyFile' => RAILS_ROOT + '/.ssh/gitolite_admin_id_rsa.pub', + 'gitoliteIdentityFile' => RAILS_ROOT + '/../.ssh/gitolite_admin_id_rsa', + 'gitoliteIdentityPublicKeyFile' => RAILS_ROOT + '/../.ssh/gitolite_admin_id_rsa.pub', 'allProjectsUseGit' => 'false', 'deleteGitRepositories' => 'false', 'gitRepositoriesShowUrl' => 'true', @@ -26,14 +26,15 @@ 'gitCacheMaxElements' => '100', 'gitCacheMaxSize' => '16', 'gitHooksDebug' => 'false', - 'gitHooksAreAsynchronous' => 'true' + 'gitHooksAreAsynchronous' => 'true', + 'gitLogLevel' => '0' }, :partial => 'redmine_git_hosting' - project_module :repository do - permission :create_repository_mirrors, :repository_mirrors => :create - permission :view_repository_mirrors, :repository_mirrors => :index - permission :edit_repository_mirrors, :repository_mirrors => :edit - end + project_module :repository do + permission :create_repository_mirrors, :repository_mirrors => :create + permission :view_repository_mirrors, :repository_mirrors => :index + permission :edit_repository_mirrors, :repository_mirrors => :edit + end end require "dispatcher" Dispatcher.to_prepare :redmine_git_patches do @@ -52,6 +53,9 @@ require 'git_hosting/patches/repository_patch' Repository.send(:include, GitHosting::Patches::RepositoryPatch) + require 'git_hosting/patches/project_patch' + Project.send(:include, GitHosting::Patches::ProjectPatch) + require 'stringio' require_dependency 'redmine/scm/adapters/git_adapter' require 'git_hosting/patches/git_adapter_patch' @@ -90,8 +94,8 @@ class GitRepoUrlHook < Redmine::Hook::ViewListener Project.send(:has_many, :repository_mirrors, :dependent => :destroy) # initialize observer -config.after_initialize do - if config.action_controller.perform_caching +#config.after_initialize do +# if config.action_controller.perform_caching ActiveRecord::Base.observers = ActiveRecord::Base.observers << GitHostingObserver ActiveRecord::Base.observers = ActiveRecord::Base.observers << GitHostingSettingsObserver @@ -101,6 +105,6 @@ class GitRepoUrlHook < Redmine::Hook::ViewListener ActionController::Dispatcher.to_prepare(:git_hosting_settings_observer_reload) do GitHostingSettingsObserver.instance.reload_this_observer end - end -end +# end +#end diff --git a/lib/git_adapter_hooks.rb b/lib/git_adapter_hooks.rb old mode 100755 new mode 100644 index 0288f122b..844c6379a --- a/lib/git_adapter_hooks.rb +++ b/lib/git_adapter_hooks.rb @@ -8,7 +8,7 @@ class GitAdapterHooks @@check_hooks_installed_cached = nil def self.check_hooks_installed - if not @@check_hooks_installed_cached.nil? and (Time.new - @@check_hooks_installed_stamp <= 0.5): + if not @@check_hooks_installed_cached.nil? and (Time.new - @@check_hooks_installed_stamp <= 0.5) return @@check_hooks_installed_cached end @@ -22,7 +22,7 @@ def self.check_hooks_installed if (!post_receive_exists) || post_receive_length_is_zero logger.info "\"post-receive\" not handled by gitolite, installing it..." install_hook("post-receive.redmine_gitolite.rb") - logger.info "\"post-receive.redmine_gitolite\ installed" + logger.info "\"post-receive.redmine_gitolite\" installed" logger.info "Running \"gl-setup\" on the gitolite install..." %x[#{GitHosting.git_user_runner} gl-setup] update_global_hook_params @@ -50,7 +50,11 @@ def self.check_hooks_installed end end - + def self.setup_hooks_pid(project_ids) + project_ids = (project_ids.is_a?(Array) ? project_ids : [project_ids]) + projects = project_ids.collect { |p| Project.find(p) } + self.setup_hooks(projects) + end def self.setup_hooks(projects=nil) check_hooks_installed update_global_hook_params diff --git a/lib/git_hosting.rb b/lib/git_hosting.rb index 8bcea3432..8258c015a 100755 --- a/lib/git_hosting.rb +++ b/lib/git_hosting.rb @@ -5,6 +5,7 @@ require 'gitolite_conf.rb' require 'git_adapter_hooks.rb' +require 'git_hosting_observer.rb' module GitHosting @@ -12,7 +13,10 @@ module GitHosting def self.logger # it may be useful to redefine this for some debugging purposes # but by default, we're just going to use the default Rails logger - return Rails.logger + #return Rails.logger + logger = Logger.new(RAILS_ROOT + '/log/git.log', 'daily') + logger.level = Setting.plugin_redmine_git_hosting['gitLogLevel'].to_i + return logger end @@web_user = nil @@ -59,7 +63,7 @@ def self.mirror_push_public_key @@sudo_git_to_web_user_stamp = nil @@sudo_git_to_web_user_cached = nil def self.sudo_git_to_web_user - if not @@sudo_git_to_web_user_cached.nil? and (Time.new - @@sudo_git_to_web_user_stamp <= 0.5): + if not @@sudo_git_to_web_user_cached.nil? and (Time.new - @@sudo_git_to_web_user_stamp <= 0.5) return @@sudo_git_to_web_user_cached end logger.info "Testing if git user(\"#{git_user}\") can sudo to web user(\"#{web_user}\")" @@ -83,7 +87,7 @@ def self.sudo_git_to_web_user @@sudo_web_to_git_user_stamp = nil @@sudo_web_to_git_user_cached = nil def self.sudo_web_to_git_user - if not @@sudo_web_to_git_user_cached.nil? and (Time.new - @@sudo_web_to_git_user_stamp <= 0.5): + if not @@sudo_web_to_git_user_cached.nil? and (Time.new - @@sudo_web_to_git_user_stamp <= 0.5) return @@sudo_web_to_git_user_cached end logger.info "Testing if web user(\"#{web_user}\") can sudo to git user(\"#{git_user}\")" @@ -104,19 +108,8 @@ def self.sudo_web_to_git_user return @@sudo_web_to_git_user_cached end - def self.get_full_parent_path(project, is_file_path) - parent_parts = []; - p = project - while p.parent - parent_id = p.parent.identifier.to_s - parent_parts.unshift(parent_id) - p = p.parent - end - return is_file_path ? File.join(parent_parts) : parent_parts.join("/") - end - def self.repository_name project - return "#{get_full_parent_path(project, false)}/#{project.identifier}".sub(/^\//, "") + return "#{project.identifier}".sub(/^\//, "") end def self.repository_path project @@ -136,7 +129,7 @@ def self.add_route_for_project(p) def self.add_route_for_project_with_map(p,m) repo = p.repository if repo.is_a?(Repository::Git) - repo_name= p.parent ? File.join(GitHosting::get_full_parent_path(p, true),p.identifier) : p.identifier + repo_name = p.identifier repo_path = repo_name + ".git" m.connect repo_path, :controller => 'git_http', :p1 => '', :p2 =>'', :p3 =>'', :id=>"#{p[:identifier]}", :path=>"#{repo_path}" m.connect repo_path, :controller => 'git_http', :p1 => '', :p2 =>'', :p3 =>'', :id=>"#{p[:identifier]}", :path=>"#{repo_path}" @@ -341,12 +334,17 @@ def self.move_repository(old_name, new_name) # unlock unlock() - end + end + + def self.update_repositories_pid(project_ids, is_repo_delete) + project_ids = (project_ids.is_a?(Array) ? project_ids : [project_ids]) + projects = project_ids.collect { |p| Project.find(p) } + self.update_repositories(projects, is_repo_delete) + end @@recursionCheck = false def self.update_repositories(projects, is_repo_delete) - if(defined?(@@recursionCheck)) if(@@recursionCheck) return @@ -354,7 +352,7 @@ def self.update_repositories(projects, is_repo_delete) end @@recursionCheck = true - logger.debug "Updating repositories..." + logger.debug 'Updating repositories: ' + projects.join{ |p| p.name + ' ' } projects = (projects.is_a?(Array) ? projects : [projects]) @@ -386,6 +384,8 @@ def self.update_repositories(projects, is_repo_delete) repo_name = repository_name(project) + logger.debug 'Updating ' + project.name + #check for delete -- if delete we can just #delete repo, and ignore updating users/public keys if is_repo_delete @@ -450,7 +450,13 @@ def self.update_repositories(projects, is_repo_delete) if conf.changed? conf.save changed = true - end + end + + if changed + logger.debug 'Configuration changed' + else + logger.debug 'Configuration NOT changed' + end if changed %x[env GIT_SSH=#{gitolite_ssh()} git --git-dir='#{local_dir}/gitolite-admin/.git' --work-tree='#{local_dir}/gitolite-admin' add keydir/*] @@ -459,13 +465,21 @@ def self.update_repositories(projects, is_repo_delete) %x[env GIT_SSH=#{gitolite_ssh()} git --git-dir='#{local_dir}/gitolite-admin/.git' --work-tree='#{local_dir}/gitolite-admin' config user.name 'Redmine'] %x[env GIT_SSH=#{gitolite_ssh()} git --git-dir='#{local_dir}/gitolite-admin/.git' --work-tree='#{local_dir}/gitolite-admin' commit -a -m 'updated by Redmine' ] %x[env GIT_SSH=#{gitolite_ssh()} git --git-dir='#{local_dir}/gitolite-admin/.git' --work-tree='#{local_dir}/gitolite-admin' push ] - end + end # Set post recieve hooks for new projects # We need to do this AFTER push, otherwise necessary repos may not be created yet if new_projects.length > 0 GitAdapterHooks.setup_hooks(new_projects) - end + end + + projects.each do |p| + next if p.repository.nil? + GitHostingObserver.set_update_active false + p.repository.update_finished = Time.new + p.repository.save + GitHostingObserver.set_update_active true + end unlock() end @@ -494,7 +508,14 @@ def self.check_hooks_installed unlock() end installed - end + end + def self.setup_hooks_pid(projects=[]) + if lock(5) + GitAdapterHooks.setup_hooks_pid(projects) + unlock() + end + end + def self.setup_hooks(projects=nil) if lock(5) GitAdapterHooks.setup_hooks(projects) diff --git a/lib/git_hosting/patches/git_adapter_patch.rb b/lib/git_hosting/patches/git_adapter_patch.rb index d97624bd2..20adc4ec3 100644 --- a/lib/git_hosting/patches/git_adapter_patch.rb +++ b/lib/git_hosting/patches/git_adapter_patch.rb @@ -38,7 +38,7 @@ def client_command_with_sudo def scm_cmd_with_sudo(*args, &block) args.each do |a| - a.gsub!(/^\.\-\w_\:]/, '') + a.gsub!(/^\.\-\w_\:\]/, '') end max_cache_time = (Setting.plugin_redmine_git_hosting['gitCacheMaxTime']).to_i # in seconds, default = 60 max_cache_elements = (Setting.plugin_redmine_git_hosting['gitCacheMaxElements']).to_i # default = 100 diff --git a/lib/git_hosting/patches/project_patch.rb b/lib/git_hosting/patches/project_patch.rb new file mode 100644 index 000000000..f599af785 --- /dev/null +++ b/lib/git_hosting/patches/project_patch.rb @@ -0,0 +1,9 @@ +module GitHosting + module Patches + module ProjectPatch + def join + return '' + end + end + end +end diff --git a/lib/git_hosting/patches/projects_controller_patch.rb b/lib/git_hosting/patches/projects_controller_patch.rb index 0937ff7c1..f21c981d2 100644 --- a/lib/git_hosting/patches/projects_controller_patch.rb +++ b/lib/git_hosting/patches/projects_controller_patch.rb @@ -16,7 +16,7 @@ def git_repo_init if @project.module_enabled?('repository') && Setting.plugin_redmine_git_hosting['allProjectsUseGit'] == "true" GitHostingObserver.set_update_active(false) repo = Repository.factory("Git") - repo_name= @project.parent ? File.join(GitHosting::get_full_parent_path(@project, true),@project.identifier) : @project.identifier + repo_name = @project.identifier repo.url = repo.root_url = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'], "#{repo_name}.git") @project.repository = repo repo.save @@ -34,39 +34,13 @@ def disable_git_daemon_if_not_public end end end - end - - def update_git_repo_for_new_parent - if @project.repository != nil - if @project.repository.is_a?(Repository::Git) - old_parent_id = @project.parent ? @project.parent.id : nil - new_parent_id = params[:project].has_key?('parent_id') ? params[:project]['parent_id'] : nil - old_parent_id = old_parent_id.to_s.strip.chomp == "" ? nil : old_parent_id - new_parent_id = new_parent_id.to_s.strip.chomp == "" ? nil : new_parent_id - if old_parent_id.to_s != new_parent_id.to_s - old_parent = old_parent_id != nil ? Project.find_by_id(old_parent_id) : nil - new_parent = new_parent_id != nil ? Project.find_by_id(new_parent_id) : nil - - old_name = old_parent.is_a?(Project) ? File.join(GitHosting::get_full_parent_path(old_parent, true), old_parent.identifier,@project.identifier).gsub(/^\//, "") : @project.identifier - new_name = new_parent.is_a?(Project) ? File.join(GitHosting::get_full_parent_path(new_parent, true), new_parent.identifier,@project.identifier).gsub(/^\//, "") : @project.identifier - - @project.repository.url = @project.repository.root_url = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'], "#{new_name}.git") - @project.repository.save - GitHosting::move_repository( old_name, new_name ) - end - end - end - end - - + end def self.included(base) base.class_eval do unloadable end base.send(:after_filter, :git_repo_init, :only=>:create) - - base.send(:before_filter, :update_git_repo_for_new_parent, :only=>:update) base.send(:after_filter, :disable_git_daemon_if_not_public, :only=>:update) end end diff --git a/lib/git_hosting/patches/repositories_controller_patch.rb b/lib/git_hosting/patches/repositories_controller_patch.rb index 72e71c999..213f09b5b 100644 --- a/lib/git_hosting/patches/repositories_controller_patch.rb +++ b/lib/git_hosting/patches/repositories_controller_patch.rb @@ -13,8 +13,9 @@ def edit_with_scm_settings GitHosting.logger.debug "On edit_with_scm_settings" params[:repository] ||= {} if params[:repository_scm] == "Git" - repo_name= @project.parent ? File.join(GitHosting::get_full_parent_path(@project, true),@project.identifier) : @project.identifier - params[:repository][:url] = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'], "#{repo_name}.git") + repo_name = @project.identifier + params[:repository][:url] = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'],"#{repo_name}.git") + params[:repository][:root_url] = params[:repository][:url] end if params[:repository_scm] == "Git" || @project.repository.is_a?(Repository::Git) @@ -42,8 +43,8 @@ def edit_with_scm_settings end end - GitHosting.update_repositories(@project, false) if !@project.repository.nil? - GitHosting.setup_hooks(@project) if !@project.repository.nil? + GitHosting.delay.update_repositories_pid([@project.id], false) if !@project.repository.nil? + GitHosting.delay.setup_hooks_pid([@project.id]) if !@project.repository.nil? else edit_without_scm_settings diff --git a/lib/gitolite_conf.rb b/lib/gitolite_conf.rb index 1a57a3e88..5b0e8029b 100755 --- a/lib/gitolite_conf.rb +++ b/lib/gitolite_conf.rb @@ -118,6 +118,9 @@ def rights end def add perm, users + # srnatoma: musime ziskat cast pred @ (chovanie gitolite) + users.collect! { |u| u.split('@').first } + @rights[perm.to_sym] ||= [] @rights[perm.to_sym] << users @rights[perm.to_sym].flatten! diff --git a/lib/tasks/gitolite.rake b/lib/tasks/gitolite.rake new file mode 100644 index 000000000..84ac6af25 --- /dev/null +++ b/lib/tasks/gitolite.rake @@ -0,0 +1,27 @@ +namespace :gitolite do + desc "update gitolite repositories" + task :update_repositories => [:environment] do + projects = Project.active + puts "Updating repositories for projects #{projects.join(' ')}" + GitHosting.update_repositories(projects, false) + end + desc "fetch commits from gitolite repositories" + task :fetch_changes => [:environment] do + Repository.fetch_changesets + end + + desc "update repository paths in database" + task(:update_repository_paths => [:environment]) do + Project.find(:all).each do |p| + repo_name = p.identifier + r = p.repository + r.url = r.root_url = File.join(Setting.plugin_redmine_git_hosting['gitRepositoryBasePath'], "#{repo_name}.git") unless r.nil? + r.save unless r.nil? + end + end + + desc "setup git hooks" + task(:setup_hooks => [:environment]) do + GitHosting::GitAdapterHooks.setup_hooks + end +end diff --git a/tasks/gitolite.rake b/tasks/gitolite.rake deleted file mode 100644 index e15d136d3..000000000 --- a/tasks/gitolite.rake +++ /dev/null @@ -1,13 +0,0 @@ -namespace :gitolite do - desc "update gitolite repositories" - task :update_repositories => [:environment] do - projects = Project.active - puts "Updating repositories for projects #{projects.join(' ')}" - GitHosting.update_repositories(projects, false) - end - desc "fetch commits from gitolite repositories" - task :fetch_changes => [:environment] do - Repository.fetch_changesets - end - -end

<%=l(:label_public_keys)%>

<%=l(:label_public_keys)%>

<%=l(:label_no_public_keys)%>

<%=l(:label_no_public_keys)%>