diff --git a/README.md b/README.md index fd7d176..0a3a8d5 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,42 @@ redmine_repository_fetch ======================== Redmine plugin to automatically clone and fetch referenced repositories + +Currently the plugin hardcodes this config, change it for your use-case: + +``` + PATTERNS = [ + { :pattern => "/redmine_git_fetch/github.com/", + :uri_prefix => "git@github.com:", + :key => "/home/redmine/data/keys/id_rsa" + }, + { :pattern => "/redmine_git_fetch/gitlab.com/", + :uri_prefix => "git@gitlab.com:", + :key => "/home/redmine/data/keys/id_rsa" + }, + { :pattern => "/redmine_git_fetch/git.ewdev.ca/", + :uri_prefix => "git@git.ewdev.ca:", + :key => "/home/redmine/data/keys/id_rsa" + } + ] +``` + +Once you have it setup, do the following: + +Add `/redmine_git_fetch/github.com/evolvingweb/sitediff.git` to a repo. The +plugin will automatically detect the prefix `/redmine_git_fetch/github.com/` +and figure out it needs to clone `git@github.com:evolvingweb/sitediff.git`. +If it's already cloned it will fetch instead. In all cases you need to specify +a path to a private key to use, since all clones happen over SSH. + +Note that `/redmine_git_fetch` folder will get auto-created. + +The plugin currently doesn't fetch any repos outside its purview. + +It also needs to be run as follows: + +``` +bundle exec rails runner "RepositoryFetch.fetch" -e production +``` + +Tested on Redmine 2.6. diff --git a/init.rb b/init.rb new file mode 100644 index 0000000..280c44b --- /dev/null +++ b/init.rb @@ -0,0 +1,10 @@ +require 'redmine' +require_dependency "repository_fetch/fetch" + +Redmine::Plugin.register :repository_fetch do + name 'Repository Fetch' + author 'Alex Dergachev' + url 'https://github.com/dergachev/redmine_repository_fetch' + description 'Automatically clone and fetch referenced repositories' + version '0.0.1' +end diff --git a/lib/repository_fetch/fetch.rb b/lib/repository_fetch/fetch.rb new file mode 100644 index 0000000..31691d3 --- /dev/null +++ b/lib/repository_fetch/fetch.rb @@ -0,0 +1,62 @@ +module RepositoryFetch + + def self.logger + ::Rails.logger + end + + PATTERNS = [ + { :pattern => "/redmine_git_fetch/github.com/", + :uri_prefix => "git@github.com:", + :key => "/home/redmine/data/keys/id_rsa" + }, + { :pattern => "/redmine_git_fetch/gitlab.com/", + :uri_prefix => "git@gitlab.com:", + :key => "/home/redmine/data/keys/id_rsa" + }, + { :pattern => "/redmine_git_fetch/git.ewdev.ca/", + :uri_prefix => "git@git.ewdev.ca:", + :key => "/home/redmine/data/keys/id_rsa" + } + ] + + def self.clone_or_fetch(repository) + return unless repository.scm_name == "Git" + + path = repository.url + + p = PATTERNS.find { |p| path.starts_with? p[:pattern] } + unless p + # TODO: figure out how to handle non-matching repos. + # eg. skip them, try fetching them, throw warning or not? + proj = repository.project.identifier + logger.warn "repository_fetch: no match for '#{path}' in project '#{proj}'" + return + end + + # If dir exists and non-empty, should be safe to 'git fetch' + if Dir.exists?(path) && Dir.entries(path) != [".", ".."] + puts "Running git fetch on #{path}" + puts self.exec_with_key "git -C #{path} fetch --all", p[:key] + else + # try cloning the repo + url = path.sub( p[:pattern], p[:uri_prefix]) + puts "Matched new URL, trying to clone: " + url + puts self.exec_with_key "git clone --mirror #{url} #{path}", p[:key] + end + end + + def self.exec_with_key(cmd, keyfile) + return `ssh-agent bash -c 'ssh-add #{keyfile}; #{cmd}'` + end + + def self.fetch + Project.active.has_module(:repository).all.each do |project| + project.repositories.each do |repository| + self.clone_or_fetch(repository) + end + end + end + + class Fetcher + end +end