-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Configuration | ||
module Syncer | ||
module SCM | ||
class Base < Syncer::Base | ||
class << self | ||
|
||
attr_accessor :protocol, :username, :password, :ip, :port, :path, :additional_options | ||
|
||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Configuration | ||
module Syncer | ||
module SCM | ||
class Git < Base | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Configuration | ||
module Syncer | ||
module SCM | ||
class SVN < Base | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Syncer | ||
module SCM | ||
class Base < Syncer::Base | ||
|
||
## | ||
# In a server url such as: | ||
# https://jimmy:password@example.com:80 | ||
# -> [protocol]://[username]:[password][ip]:[port] | ||
attr_accessor :protocol, :username, :password, :ip, :port | ||
|
||
## | ||
# repositories is an alias to directories; provided just for clarity | ||
alias :repositories :directories | ||
alias :repositories= :directories= | ||
|
||
## | ||
# Instantiates a new Repository Syncer object | ||
# and sets the default configuration | ||
def initialize | ||
load_defaults! | ||
|
||
@path ||= 'backups' | ||
@directories = Array.new | ||
end | ||
|
||
def perform! | ||
Logger.message("#{ self.class } started syncing '#{ path }'.") | ||
repositories.each do |repository| | ||
backup_repository! repository | ||
end | ||
end | ||
|
||
def authority | ||
"#{protocol}://#{credentials}#{ip}#{prefixed_port}" | ||
end | ||
|
||
def repository_urls | ||
repositories.collect{ |r| repository_url(r) } | ||
end | ||
|
||
def repository_url(repository) | ||
"#{authority}#{repository}" | ||
end | ||
|
||
def repository_local_path(repository) | ||
File.join(path, repository) | ||
end | ||
|
||
def repository_absolute_local_path(repository) | ||
File.absolute_path(repository_local_path(repository)) | ||
end | ||
|
||
def repository_local_container_path(repository) | ||
File.dirname(repository_local_path(repository)) | ||
end | ||
|
||
def create_repository_local_container!(repository) | ||
FileUtils.mkdir_p(repository_local_container_path(repository)) | ||
end | ||
|
||
private | ||
|
||
def credentials | ||
"#{username}#{prefixed_password}@" if username | ||
end | ||
|
||
def prefixed_password | ||
":#{password}" if password | ||
end | ||
|
||
def prefixed_port | ||
":#{port}" if port | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Syncer | ||
module SCM | ||
class Git < Base | ||
|
||
attr_accessor :username, :password, :host, :protocol, :port, :repo_path, :path | ||
|
||
def initialize(&block) | ||
super | ||
|
||
@protocol ||= 'git' | ||
|
||
instance_eval(&block) if block_given? | ||
end | ||
|
||
def local_repository_exists?(repository) | ||
local_path = repository_local_path(repository) | ||
run "cd #{local_path} && git rev-parse --git-dir > /dev/null 2>&1" | ||
return true | ||
rescue Errors::CLI::SystemCallError | ||
Logger.message("#{local_path} is not a repository") | ||
return false | ||
end | ||
|
||
def clone_repository!(repository) | ||
Logger.message("Cloning repository in '#{repository_local_path(repository)}'.") | ||
create_repository_local_container!(repository) | ||
run "cd #{repository_local_container_path(repository)} && git clone --bare #{repository_url(repository)}" | ||
end | ||
|
||
def update_repository!(repository) | ||
local_path = repository_local_path(repository) | ||
Logger.message("Updating repository in '#{local_path}'.") | ||
run "cd #{local_path} && git fetch --all" | ||
end | ||
|
||
def backup_repository!(repository) | ||
if local_repository_exists?(repository) | ||
update_repository!(repository) | ||
else | ||
clone_repository!(repository) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# encoding: utf-8 | ||
|
||
module Backup | ||
module Syncer | ||
module SCM | ||
class SVN < Base | ||
|
||
def initialize(&block) | ||
|
||
super | ||
|
||
@protocol ||= "http" | ||
|
||
instance_eval(&block) if block_given? | ||
end | ||
|
||
def local_repository_exists?(repository) | ||
run "svnadmin verify #{repository_local_path(repository)}" | ||
return true | ||
rescue Errors::CLI::SystemCallError | ||
return false | ||
end | ||
|
||
def initialize_repository!(repository) | ||
local_path = repository_local_path(repository) | ||
absolute_path = repository_absolute_local_path(repository) | ||
url = repository_url(repository) | ||
hook_path = File.join(local_path, 'hooks', 'pre-revprop-change') | ||
|
||
Logger.message("Initializing empty svn repository in '#{local_path}'.") | ||
|
||
create_repository_local_container!(repository) | ||
|
||
run "svnadmin create '#{local_path}'" | ||
run "echo '#!/bin/sh' > '#{hook_path}'" | ||
run "chmod +x '#{hook_path}'" | ||
run "svnsync init file://#{absolute_path} #{url}" | ||
end | ||
|
||
def update_repository!(repository) | ||
absolute_path = repository_absolute_local_path(repository) | ||
local_path = repository_local_path(repository) | ||
|
||
Logger.message("Updating svn repository in '#{local_path}'.") | ||
run("svnsync sync file://#{absolute_path} --non-interactive") | ||
end | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
kikito
Author
|
||
|
||
|
||
def backup_repository!(repository) | ||
initialize_repository!(repository) unless local_repository_exists?(repository) | ||
update_repository!(repository) | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# encoding: utf-8 | ||
|
||
require File.expand_path('../../../../spec_helper.rb', __FILE__) | ||
|
||
describe Backup::Configuration::Syncer::SCM do | ||
before do | ||
Backup::Configuration::Syncer::SCM::Base.defaults do |default| | ||
default.protocol = 'http' | ||
default.username = 'my_user_name' | ||
default.password = 'secret' | ||
default.ip = 'example.com' | ||
default.port = 1234 | ||
default.path = '~/backups/' | ||
default.additional_options = 'some_additional_options' | ||
# base.directories/repositories # can not have a default value | ||
|
||
end | ||
end | ||
|
||
after { Backup::Configuration::Syncer::SCM::Base.clear_defaults! } | ||
|
||
it 'should set the default base configuration' do | ||
base = Backup::Configuration::Syncer::SCM::Base | ||
base.protocol.should == 'http' | ||
base.username.should == 'my_user_name' | ||
base.password.should == 'secret' | ||
base.ip.should == 'example.com' | ||
base.port.should == 1234 | ||
base.path.should == '~/backups/' | ||
base.additional_options == 'some_additional_options' | ||
end | ||
|
||
describe '#clear_defaults!' do | ||
it 'should clear all the defaults, resetting them to nil' do | ||
Backup::Configuration::Syncer::SCM::Base.clear_defaults! | ||
|
||
base = Backup::Configuration::Syncer::SCM::Base | ||
base.protocol.should == nil | ||
base.username.should == nil | ||
base.password.should == nil | ||
base.ip.should == nil | ||
base.port.should == nil | ||
base.path.should == nil | ||
base.additional_options == nil | ||
end | ||
end | ||
|
||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# encoding: utf-8 | ||
|
||
require File.expand_path('../../../../spec_helper.rb', __FILE__) | ||
|
||
describe Backup::Configuration::Syncer::SCM::Git do | ||
it 'should be a subclass of SCM::Base' do | ||
git = Backup::Configuration::Syncer::SCM::Git | ||
git.superclass.should == Backup::Configuration::Syncer::SCM::Base | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# encoding: utf-8 | ||
|
||
require File.expand_path('../../../../spec_helper.rb', __FILE__) | ||
|
||
describe Backup::Configuration::Syncer::SCM::SVN do | ||
it 'should be a subclass of SCM::Base' do | ||
svn = Backup::Configuration::Syncer::SCM::SVN | ||
svn.superclass.should == Backup::Configuration::Syncer::SCM::Base | ||
end | ||
end |
Why
svnsync
instead ofsvnadmin hotcopy
? I don't know the semantics of the former, but the latter allows the repository to be active during the backup; that is, it won't lose transactions in-flight. But, it's been a long time since I looked at backing up svn repositories; I'm probably out of date.