gitbak 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +57 -10
- data/bin/gitbak +0 -2
- data/lib/gitbak/config.rb +12 -39
- data/lib/gitbak/exec.rb +18 -7
- data/lib/gitbak/misc.rb +29 -3
- data/lib/gitbak/services.rb +16 -2
- data/lib/gitbak/version.rb +2 -2
- data/lib/gitbak.rb +22 -10
- metadata +17 -7
data/README.md
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
File : README
|
4
4
|
Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
-
Date :
|
5
|
+
Date : 2013-01-03
|
6
6
|
|
7
|
-
Copyright : Copyright (C)
|
8
|
-
Version : v0.
|
7
|
+
Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
Version : v0.4.0
|
9
9
|
|
10
10
|
<!-- }}}1 -->
|
11
11
|
|
@@ -14,30 +14,73 @@
|
|
14
14
|
|
15
15
|
gitbak - bitbucket/github/gist backup
|
16
16
|
|
17
|
-
GitBak
|
18
|
-
|
19
|
-
|
17
|
+
GitBak mirrors Bitbucket/GitHub/Gist repositories; paths, users, and
|
18
|
+
authentication are specified in ~/.gitbak.
|
19
|
+
|
20
|
+
When run, gitbak:
|
21
|
+
|
22
|
+
* asks for unspecified passwords;
|
23
|
+
* lists repositories using APIs - authenticating if necessary;
|
24
|
+
* clones/updates repositories;
|
25
|
+
* shows a summary (if verbose)
|
20
26
|
|
21
27
|
<!-- }}}1 -->
|
22
28
|
|
23
29
|
## Usage
|
24
30
|
<!-- \{{{1 -->
|
25
31
|
|
26
|
-
$ gitbak --help
|
27
|
-
$ vim ~/.gitbak
|
28
|
-
$ gitbak -v
|
32
|
+
$ gitbak --help # show options
|
33
|
+
$ vim ~/.gitbak # configure
|
34
|
+
$ gitbak -v # mirror
|
35
|
+
$ time gitbak -v 2>&1 | tee log # w/ logfile
|
36
|
+
|
37
|
+
You may want to run gitbak as a cron job. TODO
|
29
38
|
|
30
39
|
<!-- }}}1 -->
|
31
40
|
|
32
41
|
## Installing
|
33
42
|
<!-- \{{{1 -->
|
34
43
|
|
35
|
-
$ gem install gitbak
|
44
|
+
$ gem install gitbak # rubygems
|
36
45
|
|
37
46
|
Get it at https://github.com/obfusk/gitbak. Depends: git, ruby.
|
38
47
|
|
39
48
|
<!-- }}}1 -->
|
40
49
|
|
50
|
+
## Configuration
|
51
|
+
<!-- \{{{1 -->
|
52
|
+
|
53
|
+
### Example
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
# ~/.gitbak
|
57
|
+
|
58
|
+
dir = "#{ Dir.home }/__mirror__/#{ Time.new.strftime '%Y%m%d' }"
|
59
|
+
|
60
|
+
GitBak.configure do |auth, services|
|
61
|
+
%w{ bob alice }.each do |u|
|
62
|
+
services.bitbucket "#{dir}/#{u}/bitbucket", u, auth: true
|
63
|
+
services.github "#{dir}/#{u}/github" , u, auth: true
|
64
|
+
services.gist "#{dir}/#{u}/gist" , u, auth: true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Methods
|
70
|
+
|
71
|
+
auth.<service> user[, password]
|
72
|
+
services.<service> dir, user[, options]
|
73
|
+
|
74
|
+
The (default) services are: bitbucket, github, gist. GitBak will
|
75
|
+
prompt for unspecified passwords.
|
76
|
+
|
77
|
+
#### Repository Options
|
78
|
+
|
79
|
+
:auth can be true (same user) or 'username'.
|
80
|
+
:method defaults to :ssh.
|
81
|
+
|
82
|
+
<!-- }}}1 -->
|
83
|
+
|
41
84
|
## TODO
|
42
85
|
<!-- \{{{1 -->
|
43
86
|
|
@@ -47,6 +90,8 @@
|
|
47
90
|
* tests?
|
48
91
|
* better error handling?
|
49
92
|
|
93
|
+
<!-- -->
|
94
|
+
|
50
95
|
* custom services (should be easy to add already)
|
51
96
|
* metadata (issues, wikis, ...)
|
52
97
|
* teams/organisations
|
@@ -54,6 +99,8 @@
|
|
54
99
|
* filtering
|
55
100
|
* oauth?
|
56
101
|
|
102
|
+
<!-- -->
|
103
|
+
|
57
104
|
* specify ssh key(s)?
|
58
105
|
* https clone auth?
|
59
106
|
|
data/bin/gitbak
CHANGED
data/lib/gitbak/config.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# -- ; {{{1
|
2
|
+
#
|
3
|
+
# File : gitbak/config.rb
|
4
|
+
# Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
+
# Date : 2013-01-03
|
6
|
+
#
|
7
|
+
# Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
# Licence : GPLv2
|
9
|
+
#
|
10
|
+
# -- ; }}}1
|
11
|
+
|
1
12
|
require 'gitbak/eval'
|
2
13
|
require 'gitbak/misc'
|
3
14
|
require 'gitbak/services'
|
@@ -15,45 +26,6 @@ module GitBak
|
|
15
26
|
|
16
27
|
# --
|
17
28
|
|
18
|
-
# description
|
19
|
-
INFO = 'gitbak - bitbucket/github/gist backup'
|
20
|
-
|
21
|
-
# configuration example
|
22
|
-
CONFIG_EX = <<-END.gsub(/^ {6}/, '') # {{{2
|
23
|
-
=== Example Configuration ===
|
24
|
-
|
25
|
-
$ cat >> ~/.gitbak
|
26
|
-
dir = '/path/to/mirrors/dir'
|
27
|
-
|
28
|
-
GitBak.configure do |auth, repos|
|
29
|
-
%w{ user1 user2 }.each do |u|
|
30
|
-
repos.bitbucket "\#{dir}/\#{u}/bitbucket", u, auth: true
|
31
|
-
repos.github "\#{dir}/\#{u}/github" , u, auth: true
|
32
|
-
repos.gist "\#{dir}/\#{u}/gist" , u, auth: true
|
33
|
-
end
|
34
|
-
end
|
35
|
-
^D
|
36
|
-
|
37
|
-
|
38
|
-
=== Configuration Methods ===
|
39
|
-
|
40
|
-
auth.<service> user[, password]
|
41
|
-
repos.<service> dir, user[, options]
|
42
|
-
|
43
|
-
|
44
|
-
The (default) services are: bitbucket, github, gist.
|
45
|
-
If a password is not specified, gitbak will prompt for it.
|
46
|
-
|
47
|
-
|
48
|
-
=== Optional Repository Options ===
|
49
|
-
|
50
|
-
:auth can be true (same user) or 'username'.
|
51
|
-
:method defaults to :ssh.
|
52
|
-
END
|
53
|
-
# }}}2
|
54
|
-
|
55
|
-
# --
|
56
|
-
|
57
29
|
# configuration base class
|
58
30
|
class ServiceCfg # {{{2
|
59
31
|
# data
|
@@ -115,6 +87,7 @@ module GitBak
|
|
115
87
|
# --
|
116
88
|
|
117
89
|
# load configuration file
|
90
|
+
# @raise ConfigError unless file returns Cfg
|
118
91
|
def self.load (file) # {{{2
|
119
92
|
cfg = eval File.read(file), GitBak::Eval.new.binding, file # ???
|
120
93
|
|
data/lib/gitbak/exec.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# -- ; {{{1
|
2
|
+
#
|
3
|
+
# File : gitbak/exec.rb
|
4
|
+
# Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
+
# Date : 2013-01-03
|
6
|
+
#
|
7
|
+
# Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
# Licence : GPLv2
|
9
|
+
#
|
10
|
+
# -- ; }}}1
|
11
|
+
|
1
12
|
require 'gitbak'
|
2
13
|
require 'gitbak/config'
|
3
14
|
|
@@ -7,12 +18,18 @@ require 'optparse'
|
|
7
18
|
|
8
19
|
# gitbak namespace
|
9
20
|
module GitBak
|
21
|
+
|
10
22
|
# command-line executable
|
11
23
|
module Executable
|
12
24
|
|
25
|
+
# description
|
26
|
+
INFO = 'gitbak - bitbucket/github/gist backup'
|
27
|
+
|
13
28
|
# command-line usage
|
14
29
|
USAGE = 'gitbak [<option(s)>]'
|
15
30
|
|
31
|
+
# --
|
32
|
+
|
16
33
|
# parse command line options; die on failure
|
17
34
|
def self.parse_options (args) # {{{1
|
18
35
|
args_ = args.dup
|
@@ -36,13 +53,7 @@ module GitBak
|
|
36
53
|
end
|
37
54
|
|
38
55
|
opts.on_tail('-h', '--help', 'Show this message') do
|
39
|
-
puts
|
40
|
-
exit
|
41
|
-
end
|
42
|
-
|
43
|
-
opts.on_tail('-e', '--example',
|
44
|
-
'Show example configuration') do
|
45
|
-
puts GitBak::Config::CONFIG_EX
|
56
|
+
puts INFO, '', opts
|
46
57
|
exit
|
47
58
|
end
|
48
59
|
|
data/lib/gitbak/misc.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# -- ; {{{1
|
2
|
+
#
|
3
|
+
# File : gitbak/misc.rb
|
4
|
+
# Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
+
# Date : 2013-01-03
|
6
|
+
#
|
7
|
+
# Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
# Licence : GPLv2
|
9
|
+
#
|
10
|
+
# -- ; }}}1
|
11
|
+
|
1
12
|
require 'io/console'
|
2
13
|
|
3
14
|
# --
|
@@ -47,13 +58,28 @@ module GitBak
|
|
47
58
|
line and line.chomp
|
48
59
|
end # }}}1
|
49
60
|
|
50
|
-
# execute command
|
51
|
-
|
52
|
-
|
61
|
+
# execute command
|
62
|
+
# @raise SysError on failure
|
63
|
+
def self.sys_ (cmd, *args)
|
53
64
|
system [cmd, cmd], *args or raise SysError,
|
54
65
|
"failed to run command #{ ([cmd] + args) } (#$?)"
|
55
66
|
end
|
56
67
|
|
68
|
+
# execute command (unless noact); optionally verbose
|
69
|
+
# @see sys_
|
70
|
+
def self.sys (cmd, *args) # {{{1
|
71
|
+
opts = Hash === args.last ? args.pop : {}
|
72
|
+
|
73
|
+
puts "$ #{ ([cmd] + args).join ' ' }" \
|
74
|
+
if opts[:verbose] or opts[:noact]
|
75
|
+
|
76
|
+
if opts[:noact]
|
77
|
+
puts '(not actually doing anything)'
|
78
|
+
else
|
79
|
+
sys_ cmd, *args
|
80
|
+
end
|
81
|
+
end # }}}1
|
82
|
+
|
57
83
|
end
|
58
84
|
end
|
59
85
|
|
data/lib/gitbak/services.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# -- ; {{{1
|
2
|
+
#
|
3
|
+
# File : gitbak/services.rb
|
4
|
+
# Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
+
# Date : 2013-01-03
|
6
|
+
#
|
7
|
+
# Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
# Licence : GPLv2
|
9
|
+
#
|
10
|
+
# -- ; }}}1
|
11
|
+
|
1
12
|
require 'gitbak/misc'
|
2
13
|
|
3
14
|
require 'json'
|
@@ -7,7 +18,8 @@ require 'open-uri'
|
|
7
18
|
|
8
19
|
# gitbak namespace
|
9
20
|
module GitBak
|
10
|
-
|
21
|
+
|
22
|
+
# git hosting services
|
11
23
|
module Services
|
12
24
|
|
13
25
|
# authentication error
|
@@ -51,6 +63,7 @@ module GitBak
|
|
51
63
|
# --
|
52
64
|
|
53
65
|
# get data from API
|
66
|
+
# @raise AuthError on 401
|
54
67
|
def self.api_get (service, user, auth) # {{{1
|
55
68
|
url = "https://#{APIS[service][user]}"
|
56
69
|
opts = auth ? { AUTH => [auth[:user], auth[:pass]] } : {}
|
@@ -71,7 +84,8 @@ module GitBak
|
|
71
84
|
|
72
85
|
# get repositories from service; uses api_get if service in APIS,
|
73
86
|
# api_get_<service> otherwise
|
74
|
-
#
|
87
|
+
#
|
88
|
+
# @return [<Hash>] [!{name:, remote:, description:},...]
|
75
89
|
def self.repositories (service, cfg, auth)
|
76
90
|
rem = REMOTES[service][cfg.fetch(:method, :ssh).to_sym]
|
77
91
|
args = [service, cfg[:user], auth]
|
data/lib/gitbak/version.rb
CHANGED
data/lib/gitbak.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# -- ; {{{1
|
2
|
+
#
|
3
|
+
# File : gitbak.rb
|
4
|
+
# Maintainer : Felix C. Stegerman <flx@obfusk.net>
|
5
|
+
# Date : 2013-01-03
|
6
|
+
#
|
7
|
+
# Copyright : Copyright (C) 2013 Felix C. Stegerman
|
8
|
+
# Licence : GPLv2
|
9
|
+
#
|
10
|
+
# -- ; }}}1
|
11
|
+
|
1
12
|
require 'gitbak/misc'
|
2
13
|
require 'gitbak/services'
|
3
14
|
require 'gitbak/version'
|
@@ -17,23 +28,24 @@ module GitBak
|
|
17
28
|
|
18
29
|
# clone (from remote) or update repository (in dir); optionally
|
19
30
|
# verbose
|
20
|
-
def self.mirror_repo (verbose, remote, dir)
|
31
|
+
def self.mirror_repo (verbose, noact, remote, dir) # {{{1
|
21
32
|
name = repo_name remote
|
22
33
|
name_ = name + '.git'
|
23
34
|
repo_dir = "#{dir}/#{name_}"
|
24
35
|
|
36
|
+
sys = ->(args) { Misc.sys *args, verbose: verbose, noact: noact }
|
37
|
+
|
25
38
|
FileUtils.mkdir_p dir
|
26
39
|
|
27
40
|
if Misc.exists? repo_dir
|
28
|
-
puts "$ cd #{repo_dir}" if verbose
|
41
|
+
puts "$ cd #{repo_dir}" if verbose or noact
|
29
42
|
FileUtils.cd(repo_dir) do
|
30
|
-
|
43
|
+
sys[ %w{ git remote update } ]
|
31
44
|
end
|
32
45
|
else
|
33
|
-
puts "$ cd #{dir}" if verbose
|
46
|
+
puts "$ cd #{dir}" if verbose or noact
|
34
47
|
FileUtils.cd(dir) do
|
35
|
-
|
36
|
-
*( %w{ git clone --mirror -n } + [remote, name_] )
|
48
|
+
sys[ %w{ git clone --mirror -n } + [remote, name_] ]
|
37
49
|
end
|
38
50
|
end
|
39
51
|
end # }}}1
|
@@ -82,19 +94,19 @@ module GitBak
|
|
82
94
|
end # }}}1
|
83
95
|
|
84
96
|
# mirror repositories; optionally verbose
|
85
|
-
def self.mirror verbose, repos
|
97
|
+
def self.mirror (verbose, noact, repos) # {{{1
|
86
98
|
repos.each do |s, usr, dir, rs|
|
87
99
|
rs.each do |r|
|
88
100
|
name, desc = r[:name], r[:description]
|
89
101
|
puts "==> #{s} | #{usr} | #{name} | #{desc} <==" if verbose
|
90
|
-
mirror_repo verbose, r[:remote], dir
|
102
|
+
mirror_repo verbose, noact, r[:remote], dir
|
91
103
|
puts if verbose
|
92
104
|
end
|
93
105
|
end
|
94
106
|
end # }}}1
|
95
107
|
|
96
108
|
# print summary
|
97
|
-
def self.summary repos
|
109
|
+
def self.summary (repos) # {{{1
|
98
110
|
puts '', '=== Summary ===', ''
|
99
111
|
repos.each do |service, usr, dir, rs|
|
100
112
|
printf " %-15s for %-20s: %10s repositories\n",
|
@@ -109,7 +121,7 @@ module GitBak
|
|
109
121
|
def self.main (verbose, noact, config)
|
110
122
|
auth, repos = process_config config
|
111
123
|
repositories = fetch verbose, auth, repos
|
112
|
-
mirror verbose, repositories
|
124
|
+
mirror verbose, noact, repositories
|
113
125
|
summary repositories if verbose
|
114
126
|
end
|
115
127
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitbak
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &8112480 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,12 +21,22 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
-
description: ! 'GitBak
|
24
|
+
version_requirements: *8112480
|
25
|
+
description: ! 'GitBak mirrors Bitbucket/GitHub/Gist repositories; paths, users,
|
26
26
|
|
27
|
-
|
27
|
+
and authentication are specified in ~/.gitbak.
|
28
28
|
|
29
|
-
|
29
|
+
|
30
|
+
When run, gitbak:
|
31
|
+
|
32
|
+
|
33
|
+
* asks for unspecified passwords;
|
34
|
+
|
35
|
+
* lists repositories using APIs - authenticating if necessary;
|
36
|
+
|
37
|
+
* clones/updates repositories;
|
38
|
+
|
39
|
+
* shows a summary (if verbose)
|
30
40
|
|
31
41
|
'
|
32
42
|
email:
|