Skip to content

Instantly share code, notes, and snippets.

@dergachev
Created December 3, 2014 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dergachev/d024800b4514de64fcb3 to your computer and use it in GitHub Desktop.
Save dergachev/d024800b4514de64fcb3 to your computer and use it in GitHub Desktop.
Initial draft for redmine_git_remote, deprecated; see https://github.com/dergachev/redmine_git_remote
# initial draft for redmine_git_remote, deprecated
module RepositoryFetch
def self.logger
::Rails.logger
end
PATTERNS = [
{ :pattern => "/redmine_git_fetch/github.com/",
:uri_prefix => "git@github.com:",
:host => "github.com",
:key => "/home/redmine/data/keys/id_rsa"
},
{ :pattern => "/redmine_git_fetch/gitlab.com/",
:uri_prefix => "git@gitlab.com:",
:host => "gitlab.com",
:key => "/home/redmine/data/keys/id_rsa"
},
{ :pattern => "/redmine_git_fetch/git.ewdev.ca/",
:uri_prefix => "git@git.ewdev.ca:",
:host => "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
RepositoryFetch::add_known_host(p[:host])
# 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 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 exec_with_key "git clone --mirror #{url} #{path}", p[:key]
end
end
def self.clone_empty(repository)
clone_path = repository.clone_path
clone_url = repository.clone_url
clone_host = repository.clone_host
RepositoryFetch::add_known_host(clone_host)
if Dir.exists? clone_path
raise "Clone path already exits: #{clone_path}"
end
unless system "git ls-remote -h #{clone_url}"
# TODO: put in validation error
raise "Invalid remote; unable to clone #{clone_url}"
end
unless system "git init --bare #{clone_path}"
#TODO validation error
raise "Unable to run git init at #{clone_path}"
end
unless system "git -C #{clone_path} remote add --tags --mirror=fetch origin #{clone_url}"
#TODO validation error
raise "Unable to run: git -C #{clone_path} remote add #{clone_url}"
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|
clone_or_fetch(repository)
end
end
end
# Checks if host is in ~/.ssh/known_hosts, adds it if not present
def self.add_known_host(host)
# if not found...
if `ssh-keygen -F #{host} | grep 'found'` == ""
# hack to work with 'docker exec' where HOME isn't set (or set to /)
ssh_known_hosts = (ENV['HOME'] == "/" or ENV['HOME'] == nil ? "/root" : ENV['HOME']) + "/.ssh/known_hosts"
puts "Authorizing #{host}"
puts `ssh-keyscan #{host} >> #{ssh_known_hosts}`
end
end
class Fetch
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment