gitlab-backup 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/Gemfile +3 -0
- data/LICENSE +13 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/bin/gitlab-backup +65 -0
- data/gitlab-backup.gemspec +26 -0
- data/lib/gitlab-backup.rb +3 -0
- data/lib/gitlab-backup/backup.rb +85 -0
- data/lib/gitlab-backup/repository.rb +104 -0
- data/lib/gitlab-backup/version.rb +7 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6222d511159cc2efb2af20f5320e858450b762a9
|
4
|
+
data.tar.gz: f72a95329b0156318369228b697f593ff60bf63e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: abbc9eb12af61b6ba0ffa05c64ad1f6049ab26ae3001eff442f68b5d723f0ab63979ea8ce3c8528670ac53d8424030949645ce8ada9031ad6606d0b6a74741ba
|
7
|
+
data.tar.gz: 7eb60590b881fd322ddcd32dce4001c3268f547f4c6dc4e63e76587c385ca0b057b79fdf5ed7fa8e362d330b5ff5857d637de9d8df2ec3fbc4d0758a4af3d737
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2012 - 2015, Seth Jackson, Uwe Kleinmann
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# GitLab Backup
|
2
|
+
|
3
|
+
A command line tool for backing up GitLab repositories.
|
4
|
+
|
5
|
+
|
6
|
+
## Prerequisites
|
7
|
+
|
8
|
+
* [Git](http://git-scm.com/)
|
9
|
+
* [Ruby](https://www.ruby-lang.org/) (>= 2.1.0)
|
10
|
+
|
11
|
+
To backup your repositories you **must** have the git on your `PATH`.
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
$ gem install gitlab-backup
|
17
|
+
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
$ gitlab-backup [options] ~/backup
|
22
|
+
|
23
|
+
See the help prompt for more info:
|
24
|
+
|
25
|
+
$ gitlab-backup --help
|
26
|
+
|
27
|
+
|
28
|
+
## Config files
|
29
|
+
|
30
|
+
You can provide a config file in the YAML format
|
31
|
+
to `gitlab-backup` via the `--config` or `-c` option.
|
32
|
+
Settings specified on the command line have precedence
|
33
|
+
over settings in the config file.
|
34
|
+
|
35
|
+
The `host` and `token` settings will be
|
36
|
+
read from the config file.
|
37
|
+
|
38
|
+
For example to backup every repository the user with the token `example` has access to
|
39
|
+
put the following in a config file and pass it to `gitlab-backup`:
|
40
|
+
|
41
|
+
host: https://gitlab.com
|
42
|
+
token: example
|
43
|
+
|
44
|
+
|
45
|
+
## License
|
46
|
+
|
47
|
+
[ISC](LICENSE)
|
48
|
+
|
49
|
+
## Thanks
|
50
|
+
|
51
|
+
This project is based on the [previous work](https://bitbucket.org/seth/bitbucket-backup) of Seth Jackson for bitbucket-backup.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/gitlab-backup
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "gitlab-backup"
|
4
|
+
require "io/console"
|
5
|
+
require "optparse"
|
6
|
+
require "yaml"
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
parser = OptionParser.new do |opts|
|
11
|
+
cmd = File.basename($0)
|
12
|
+
|
13
|
+
opts.banner = "usage: #{cmd} [options] path"
|
14
|
+
|
15
|
+
opts.on("-c", "--config FILE", "Path to config file.") do |config_file|
|
16
|
+
options["config_file"] = config_file
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on("-h", "--host HOST", "GitLab host to be backed up, e.g. http://gitlab.com") do |host|
|
20
|
+
options["host"] = host
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("-t", "--token TOKEN", "Private token for account to be backed up.") do |token|
|
24
|
+
options["token"] = token
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("--help", "Show this help message and exit.") do
|
28
|
+
puts opts
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-v", "--version", "Display the program's version and exit.") do
|
33
|
+
puts "#{cmd} (version #{Gitlab::Backup::VERSION})"
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
parser.parse!
|
39
|
+
|
40
|
+
config = {}
|
41
|
+
|
42
|
+
if options["config_file"]
|
43
|
+
begin
|
44
|
+
path = File.expand_path(options["config_file"])
|
45
|
+
|
46
|
+
config = YAML.load_file(path)
|
47
|
+
|
48
|
+
unless config
|
49
|
+
puts "Error: invalid config file: #{path}."
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
rescue YAML::SyntaxError, StandardError
|
53
|
+
puts "Error: invalid config file: #{path}."
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
config.merge!(options)
|
59
|
+
|
60
|
+
if ARGV.empty? || !config["token"] || !config["host"]
|
61
|
+
puts parser.banner
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
|
65
|
+
Gitlab::Backup.backup(config["host"], config["token"], ARGV.first)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require "gitlab-backup/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "gitlab-backup"
|
7
|
+
spec.version = Gitlab::Backup::VERSION
|
8
|
+
spec.authors = ["Uwe Kleinmann"]
|
9
|
+
spec.email = "uwe@kleinmann.org"
|
10
|
+
spec.homepage = "https://github.com/kleinmann/gitlab-backup"
|
11
|
+
spec.summary = "A tool to backup repositories from any GitLab installation."
|
12
|
+
spec.description = "A tool to backup GitLab repositories to your local machine."
|
13
|
+
spec.license = "ISC"
|
14
|
+
|
15
|
+
spec.executables = "gitlab-backup"
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split
|
18
|
+
|
19
|
+
spec.required_ruby_version = ">= 2.1.0"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rdoc", "~> 4.0"
|
24
|
+
spec.add_development_dependency "yard", "~> 0.8"
|
25
|
+
spec.add_development_dependency "redcarpet", "~> 3.2"
|
26
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "json"
|
3
|
+
require "pp"
|
4
|
+
|
5
|
+
module Gitlab
|
6
|
+
module Backup
|
7
|
+
# Begins the backup process.
|
8
|
+
#
|
9
|
+
# @param [String] host
|
10
|
+
# the host (and maybe port) of the GitLab instance to backup from.
|
11
|
+
#
|
12
|
+
# @param [String] token
|
13
|
+
# the private token of the user to backup repositories for.
|
14
|
+
#
|
15
|
+
# @param [String] backup_root
|
16
|
+
# the absolute or relative path of the directory to backup the repositories to.
|
17
|
+
def self.backup(host, token, backup_root)
|
18
|
+
backup_root = File.expand_path(backup_root)
|
19
|
+
|
20
|
+
puts
|
21
|
+
puts "Backing up repositories to #{backup_root}"
|
22
|
+
puts
|
23
|
+
|
24
|
+
repos = get_repo_list(host, token)
|
25
|
+
|
26
|
+
repos.each do |repo|
|
27
|
+
Gitlab::Backup::Repository.new(repo, token, backup_root).backup
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Checks if the specified SCM tool exists on the PATH
|
32
|
+
# and is executable.
|
33
|
+
#
|
34
|
+
# @return [Boolean]
|
35
|
+
# true if the SCM tool exists and is executable, false otherwise.
|
36
|
+
def self.have_git?
|
37
|
+
# From: http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
|
38
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
|
39
|
+
|
40
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
|
41
|
+
exts.each do |ext|
|
42
|
+
bin = "#{path}/git#{ext}"
|
43
|
+
|
44
|
+
return bin if File.executable?(bin)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
# Gets a list of the repositories the user has access to.
|
53
|
+
#
|
54
|
+
# @param [String] host
|
55
|
+
# the host (and maybe port) of the GitLab instance to backup from.
|
56
|
+
#
|
57
|
+
# @param [String] token
|
58
|
+
# the private token of the user to get repositories for.
|
59
|
+
#
|
60
|
+
# @return [Array<String>]
|
61
|
+
# the repositories the user has access to.
|
62
|
+
#
|
63
|
+
def self.get_repo_list(host, token)
|
64
|
+
uri = URI.parse("#{host}/api/v3/projects")
|
65
|
+
|
66
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
67
|
+
|
68
|
+
if host =~ /\Ahttps/
|
69
|
+
http.use_ssl = true
|
70
|
+
end
|
71
|
+
|
72
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
73
|
+
request.add_field("PRIVATE-TOKEN", token)
|
74
|
+
|
75
|
+
response = http.request(request)
|
76
|
+
|
77
|
+
if response.code == "401"
|
78
|
+
puts "Invalid token."
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
|
82
|
+
JSON.parse(response.body)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "cgi"
|
3
|
+
|
4
|
+
module Gitlab
|
5
|
+
module Backup
|
6
|
+
# The repository to back up.
|
7
|
+
#
|
8
|
+
class Repository
|
9
|
+
# @return [Hash]
|
10
|
+
# the hash of repository data from the Gitlab API.
|
11
|
+
#
|
12
|
+
attr_reader :repo
|
13
|
+
|
14
|
+
# @return [String]
|
15
|
+
# the private token for the user with which to backup the repository with.
|
16
|
+
#
|
17
|
+
attr_reader :token
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
# the absolute path of the directory to backup the repository to.
|
21
|
+
#
|
22
|
+
attr_reader :backup_root
|
23
|
+
|
24
|
+
# Creates a new repository.
|
25
|
+
#
|
26
|
+
# @param [Hash] repo
|
27
|
+
# the hash of repository data from the Gitlab API.
|
28
|
+
#
|
29
|
+
# @param [String] token
|
30
|
+
# the private token for the user with which to backup the repository with.
|
31
|
+
#
|
32
|
+
# @param [String] backup_root
|
33
|
+
# the absolute path of the directory to backup the repository to.
|
34
|
+
#
|
35
|
+
def initialize(repo, token, backup_root)
|
36
|
+
@repo = repo
|
37
|
+
@token = token
|
38
|
+
@backup_root = backup_root
|
39
|
+
end
|
40
|
+
|
41
|
+
# Performs a backup of the repository.
|
42
|
+
#
|
43
|
+
def backup
|
44
|
+
puts "Backing up: #{repo["name_with_namespace"]}."
|
45
|
+
|
46
|
+
unless Gitlab::Backup.have_git?
|
47
|
+
puts "Warning: git not found on PATH. Skipping..."
|
48
|
+
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
clone_or_update
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
# Performs a full backup of the repository's source code
|
57
|
+
# or wiki if the directory to which the backup would occur does not
|
58
|
+
# exist. Performs an incremental update (pull) otherwise.
|
59
|
+
#
|
60
|
+
def clone_or_update
|
61
|
+
path = dir_for_repo
|
62
|
+
uri = repo["ssh_url_to_repo"]
|
63
|
+
|
64
|
+
if File.exist?(path)
|
65
|
+
run_incremental_backup(path, uri)
|
66
|
+
else
|
67
|
+
run_full_backup(uri, path)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Checks whether the specified path is a repository or not.
|
72
|
+
#
|
73
|
+
# @param [String] path
|
74
|
+
# the path to check.
|
75
|
+
#
|
76
|
+
# @return [Boolean]
|
77
|
+
# true if the path is the same type of repository
|
78
|
+
# that we got from the Gitlab API, false otherwise.
|
79
|
+
def repo?(path)
|
80
|
+
FileUtils.cd(path)
|
81
|
+
|
82
|
+
system "git status -s"
|
83
|
+
|
84
|
+
return $? == 0
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_incremental_backup(path, uri)
|
88
|
+
return unless repo?(path)
|
89
|
+
|
90
|
+
FileUtils.cd(path)
|
91
|
+
|
92
|
+
system("git", "pull", uri)
|
93
|
+
end
|
94
|
+
|
95
|
+
def run_full_backup(uri, dest)
|
96
|
+
system("git", "clone", "--recursive", uri, dest)
|
97
|
+
end
|
98
|
+
|
99
|
+
def dir_for_repo
|
100
|
+
File.expand_path("#{backup_root}/#{repo["path_with_namespace"]}/src")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitlab-backup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Uwe Kleinmann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rdoc
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.8'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.8'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: redcarpet
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.2'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.2'
|
83
|
+
description: A tool to backup GitLab repositories to your local machine.
|
84
|
+
email: uwe@kleinmann.org
|
85
|
+
executables:
|
86
|
+
- gitlab-backup
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- Gemfile
|
92
|
+
- LICENSE
|
93
|
+
- README.md
|
94
|
+
- Rakefile
|
95
|
+
- bin/gitlab-backup
|
96
|
+
- gitlab-backup.gemspec
|
97
|
+
- lib/gitlab-backup.rb
|
98
|
+
- lib/gitlab-backup/backup.rb
|
99
|
+
- lib/gitlab-backup/repository.rb
|
100
|
+
- lib/gitlab-backup/version.rb
|
101
|
+
homepage: https://github.com/kleinmann/gitlab-backup
|
102
|
+
licenses:
|
103
|
+
- ISC
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 2.1.0
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 2.4.5.1
|
122
|
+
signing_key:
|
123
|
+
specification_version: 4
|
124
|
+
summary: A tool to backup repositories from any GitLab installation.
|
125
|
+
test_files: []
|
126
|
+
has_rdoc:
|