bup 0.2.0 → 0.3.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 +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +47 -31
- data/buprc +7 -2
- data/exe/bup +3 -3
- data/lib/bup/config.rb +4 -3
- data/lib/bup/tar.rb +31 -36
- data/lib/bup/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a9931bc931a38f83fe2eebebfb5939d997d685fe3bbb7fdf863860dab36c402
|
4
|
+
data.tar.gz: 701c9661de7b80acb3dec18b4ae053aec13cd41e73a4992e8f458f0cfcdaa2ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bb473340913988672050f49f0fa8ecdede02ac622b6a9630d1cd91ea3481c487da20997c313a2ee77c60cfd3a8be305e722a430506ac79c08c53cb705770ea3
|
7
|
+
data.tar.gz: 776de0097acfe0da73daa50ab4943cafab33524508c21d70e670a95c6a89d7de1d0f22de82eba354f27086da69387985a3a962a0a540f8117b0206c4b6de4ff4
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
- Communicate the backup file base name through the environment variable BUP_FILENAME.
|
4
|
+
- Rubocop fixes or ignore files.
|
5
|
+
- Add post commands, incase you want to default copy something around.
|
6
|
+
|
7
|
+
## [0.2.0] - 2021-11-13
|
8
|
+
|
3
9
|
- List profiles.
|
4
10
|
- Bug fixes against empty backup directories.
|
5
11
|
- Bug fix to print buffers using read_nonblock from popen3 streams.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,43 +1,59 @@
|
|
1
1
|
# Bup
|
2
2
|
|
3
|
-
|
3
|
+
Bup is a simple backup driver script that uses `tar` to backup files.
|
4
|
+
The idea is to simplify creating backups, full and incremental, and leave
|
5
|
+
restoration as a project for the user to untar the file where their contents
|
6
|
+
is needed.
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
gem 'bup'
|
13
|
-
```
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle install
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
|
-
$ gem install bup
|
8
|
+
Features like backup profiles, file dating, history rotation,
|
9
|
+
incremental backups, and post-processing scripting is provided.
|
22
10
|
|
23
11
|
## Usage
|
24
12
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
13
|
+
Create a file ~/.buprc with the default contents...
|
14
|
+
|
15
|
+
```yaml
|
16
|
+
---
|
17
|
+
profiles:
|
18
|
+
default:
|
19
|
+
description: Simple backup of critical files.
|
20
|
+
include:
|
21
|
+
- "$HOME"
|
22
|
+
exclude:
|
23
|
+
- "$HOME"
|
24
|
+
- "$HOME/backups"
|
25
|
+
lastrun: '2021-11-14T03:06:45 +0000'
|
26
|
+
destination: "$HOME/backups"
|
27
|
+
history: 2
|
28
|
+
tarcmd:
|
29
|
+
- tar
|
30
|
+
- cJvf
|
31
|
+
- "${BUP_FILENAME}.tar.xz"
|
32
|
+
post_cmds:
|
33
|
+
- - ls
|
34
|
+
- $BUP_FILENAME.tar.xz
|
35
|
+
```
|
32
36
|
|
33
|
-
|
37
|
+
This defines a single profile, "default". You can list
|
38
|
+
defined profiles by running `bup -l`. You run the default backup profile
|
39
|
+
simply by running `bup`. Other profiles must be selected on the command
|
40
|
+
line using `bup -p <profile name>`.
|
34
41
|
|
35
|
-
|
42
|
+
The default profile, as defined above, excludes both the `$HOME` and
|
43
|
+
`$HOME/backups` directories. Remove `$HOME` from the excludes list to actually
|
44
|
+
backup your entire home directory.
|
36
45
|
|
37
|
-
##
|
46
|
+
## Incremental Backups
|
38
47
|
|
39
|
-
|
48
|
+
By calling `bup -t incremental` an incremental backup will be run.
|
49
|
+
This runs `tar` with the `--newer` option included with the time
|
50
|
+
specified in the profile's `lastrun` setting. `Tar` will then exclude
|
51
|
+
files older than that time.
|
40
52
|
|
41
|
-
##
|
53
|
+
## Backup History
|
42
54
|
|
43
|
-
|
55
|
+
Before a new backup is run, previous backups are removed. If you run many
|
56
|
+
uncompleted backups, you will eventually remove all good backups from your
|
57
|
+
backup history. This behavior is desired because backups should nearly always
|
58
|
+
succeed and we want to ensure that disk pressure is kep lower than higher.
|
59
|
+
Higher disk pressure might cause a backup to fail.
|
data/buprc
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
---
|
2
2
|
profiles:
|
3
3
|
default:
|
4
|
-
description:
|
4
|
+
description: Simple backup of critical files.
|
5
5
|
include:
|
6
6
|
- "$HOME"
|
7
7
|
exclude:
|
8
8
|
- "$HOME"
|
9
9
|
- "$HOME/backups"
|
10
|
-
lastrun: '2021-11-
|
10
|
+
lastrun: '2021-11-14T03:06:45 +0000'
|
11
11
|
destination: "$HOME/backups"
|
12
12
|
history: 2
|
13
13
|
tarcmd:
|
14
14
|
- sudo
|
15
15
|
- tar
|
16
|
+
- cJvf
|
17
|
+
- "${BUP_FILENAME}.tar.xz"
|
18
|
+
post_cmds:
|
19
|
+
- - ls
|
20
|
+
- $BUP_FILENAME.tar.xz
|
data/exe/bup
CHANGED
@@ -23,13 +23,13 @@ OptParse.new do |opt|
|
|
23
23
|
end
|
24
24
|
|
25
25
|
opt.on("-l", "--list", "List profiles and exit.") do
|
26
|
-
config.runtime[
|
26
|
+
config.runtime["action"] = "list"
|
27
27
|
end
|
28
28
|
end.parse!
|
29
29
|
|
30
30
|
config.load(configfile) if File.exist?(configfile)
|
31
31
|
|
32
|
-
case config.runtime["action"]
|
32
|
+
case config.runtime["action"]
|
33
33
|
when "list"
|
34
34
|
config.config["profiles"].each do |key, profile|
|
35
35
|
puts "#{key} - #{profile["description"] || ""}"
|
@@ -38,4 +38,4 @@ else
|
|
38
38
|
tar = Bup::Tar.new(config)
|
39
39
|
tar.call
|
40
40
|
config.save(configfile)
|
41
|
-
end
|
41
|
+
end
|
data/lib/bup/config.rb
CHANGED
@@ -5,12 +5,13 @@ require "yaml"
|
|
5
5
|
require "date"
|
6
6
|
|
7
7
|
module Bup
|
8
|
+
# Configuration management.
|
8
9
|
class Config
|
9
|
-
@@timeformat = "%Y-%m-%dT%H:%M:%S %z"
|
10
10
|
|
11
11
|
attr_accessor :config, :runtime
|
12
12
|
|
13
13
|
def initialize
|
14
|
+
@timeformat = "%Y-%m-%dT%H:%M:%S %z"
|
14
15
|
@runtime = {
|
15
16
|
"profile" => "default",
|
16
17
|
"type" => "full"
|
@@ -45,14 +46,14 @@ module Bup
|
|
45
46
|
|
46
47
|
# Return the last run time of the backup or nil if there is none.
|
47
48
|
def lastrun(name)
|
48
|
-
DateTime.strptime(profile(name)["lastrun"] || "",
|
49
|
+
DateTime.strptime(profile(name)["lastrun"] || "", @timeformat)
|
49
50
|
rescue Date::Error
|
50
51
|
nil
|
51
52
|
end
|
52
53
|
|
53
54
|
# Return the last run time of the backup or nil if there is none.
|
54
55
|
def set_lastrun(name, date)
|
55
|
-
profile(name)["lastrun"] = date.strftime(
|
56
|
+
profile(name)["lastrun"] = date.strftime(@timeformat)
|
56
57
|
end
|
57
58
|
|
58
59
|
def profile(name)
|
data/lib/bup/tar.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "English"
|
4
|
-
require "English"
|
5
3
|
require "tempfile"
|
6
4
|
require "open3"
|
7
5
|
require "date"
|
@@ -13,9 +11,9 @@ module Bup
|
|
13
11
|
end
|
14
12
|
|
15
13
|
def expand_string(str)
|
16
|
-
while str =~ /\${?([a-zA-Z0-
|
17
|
-
all =
|
18
|
-
nm =
|
14
|
+
while str =~ /\${?([a-zA-Z0-9_]+)}?/
|
15
|
+
all = $~[0]
|
16
|
+
nm = $~[1]
|
19
17
|
str = str.sub(all, ENV[nm] || "")
|
20
18
|
end
|
21
19
|
|
@@ -36,14 +34,13 @@ module Bup
|
|
36
34
|
# Prepare the destination directory.
|
37
35
|
def prepare_destination(profile_name)
|
38
36
|
destination = expand_string(@config.profile(profile_name)["destination"] || ".")
|
39
|
-
suffix = ".tar.xz"
|
40
37
|
type = @config.runtime["type"] || "full"
|
41
38
|
|
42
39
|
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
43
40
|
|
44
41
|
filename_base = "#{profile_name}-#{type}"
|
45
42
|
filename = File.join(destination,
|
46
|
-
"#{filename_base}-#{DateTime.now.new_offset(0).strftime("%Y%m%d%H%M%S")}
|
43
|
+
"#{filename_base}-#{DateTime.now.new_offset(0).strftime("%Y%m%d%H%M%S")}")
|
47
44
|
|
48
45
|
history = @config.profile(profile_name)["history"] || 0
|
49
46
|
|
@@ -79,12 +76,9 @@ module Bup
|
|
79
76
|
|
80
77
|
raise "Missing profile #{profile_name}." unless profile
|
81
78
|
|
82
|
-
args = @config.profile(profile_name)["tarcmd"].dup || ["tar"]
|
79
|
+
args = @config.profile(profile_name)["tarcmd"].dup || ["tar", "cJvf", "${BUP_FILENAME}.tar.xz"]
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
filename = prepare_destination(profile_name)
|
87
|
-
args << filename
|
81
|
+
ENV["BUP_FILENAME"] = prepare_destination(profile_name)
|
88
82
|
|
89
83
|
if @config.runtime["type"] == "incremental"
|
90
84
|
lastrun = @config.lastrun(profile_name)
|
@@ -96,38 +90,39 @@ module Bup
|
|
96
90
|
tf = build_exclude_file(profile["exclude"] || [])
|
97
91
|
|
98
92
|
args += ["--exclude-from", tf.path]
|
99
|
-
args += (@config.profile(profile_name)["include"] || ["."])
|
93
|
+
args += (@config.profile(profile_name)["include"] || ["."])
|
94
|
+
args = args.map do |str|
|
100
95
|
expand_string(str)
|
101
96
|
end
|
102
97
|
|
103
98
|
begin
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
r.each do |stream|
|
109
|
-
begin
|
110
|
-
print stream.read_nonblock(1024)
|
111
|
-
rescue EOFError
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
99
|
+
run_cmd(*args)
|
100
|
+
ensure
|
101
|
+
tf.unlink
|
102
|
+
end
|
115
103
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
104
|
+
@config.profile(profile_name)["post_cmds"].each do |args|
|
105
|
+
run_cmd(*args.map { |c| expand_string(c) })
|
106
|
+
end
|
107
|
+
end
|
121
108
|
|
122
|
-
|
123
|
-
|
124
|
-
|
109
|
+
def run_cmd(*args)
|
110
|
+
Open3.popen3(*args) do |stdin, stdout, stderr, wait_thr|
|
111
|
+
stdin.close
|
112
|
+
x = nil
|
113
|
+
while wait_thr.status
|
114
|
+
r, _w, _e = IO.select([stdout, stderr])
|
115
|
+
r.each do |stream|
|
116
|
+
print x if (x = stream.read_nonblock(1024, exception: false))
|
125
117
|
end
|
126
|
-
|
127
|
-
STDOUT.flush
|
128
118
|
end
|
129
|
-
|
130
|
-
|
119
|
+
|
120
|
+
wait_thr.join
|
121
|
+
print x if (x = stdout.read_nonblock(1024, exception: false))
|
122
|
+
|
123
|
+
print x if (x = stderr.read_nonblock(1024, exception: false))
|
124
|
+
|
125
|
+
$stdout.flush
|
131
126
|
end
|
132
127
|
end
|
133
128
|
end
|
data/lib/bup/version.rb
CHANGED