bup 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02ca6df7a29ad6290ab682bd214dc097c70e6a7a464bbbea22b1b4d100465ec7
4
- data.tar.gz: 7bf6a98055fed3353f131e56033c876860ec6f4e22b995c4f002ffedd5e8462b
3
+ metadata.gz: 3a9931bc931a38f83fe2eebebfb5939d997d685fe3bbb7fdf863860dab36c402
4
+ data.tar.gz: 701c9661de7b80acb3dec18b4ae053aec13cd41e73a4992e8f458f0cfcdaa2ea
5
5
  SHA512:
6
- metadata.gz: f96824b5eaa8fa4089497aa3eff4daf4abf5f041931fac622ac0163aed57d79036cced77b50a771fb5c675b6abaa1473e1018b9312c8e8d5935d12fc6255c601
7
- data.tar.gz: 31aaf6faab04f3e7806bc60b082aac8bd0177aa4ade5fb40e02189289e75fef8d401aaedfce4f4abd4454aeb6679c881af0391dc732169d6eb362a820c970c9a
6
+ metadata.gz: 2bb473340913988672050f49f0fa8ecdede02ac622b6a9630d1cd91ea3481c487da20997c313a2ee77c60cfd3a8be305e722a430506ac79c08c53cb705770ea3
7
+ data.tar.gz: 776de0097acfe0da73daa50ab4943cafab33524508c21d70e670a95c6a89d7de1d0f22de82eba354f27086da69387985a3a962a0a540f8117b0206c4b6de4ff4
data/.rubocop.yml CHANGED
@@ -1,5 +1,8 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 3.0
3
+ Exclude:
4
+ - lib/bup/tar.rb
5
+ - lib/bup/config.rb
3
6
 
4
7
  Style/StringLiterals:
5
8
  Enabled: true
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bup (0.2.0)
4
+ bup (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,43 +1,59 @@
1
1
  # Bup
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bup`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Delete this and the text above, and describe your gem
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
- TODO: Write usage instructions here
26
-
27
- ## Development
28
-
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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
- ## Contributing
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
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bup. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/bup/blob/main/CODE_OF_CONDUCT.md).
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
- ## License
46
+ ## Incremental Backups
38
47
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
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
- ## Code of Conduct
53
+ ## Backup History
42
54
 
43
- Everyone interacting in the Bup project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/bup/blob/main/CODE_OF_CONDUCT.md).
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: "Simple backup of critical files."
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-11T18:45:33 +0000'
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['action'] = 'list'
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"] || "", @@timeformat)
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(@@timeformat)
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-9]+)}?/
17
- all = $LAST_MATCH_INFO[0]
18
- nm = $LAST_MATCH_INFO[1]
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")}#{suffix}")
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
- args << "cJvf"
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"] || ["."]).map do |str|
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
- Open3.popen3(*args) do |stdin, stdout, stderr, wait_thr|
105
- stdin.close
106
- while wait_thr.status
107
- r, w, e = IO.select([stdout, stderr])
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
- wait_thr.join
117
- begin
118
- print stdout.read_nonblock(1024)
119
- rescue EOFError
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
- begin
123
- print stderr.read_nonblock(1024)
124
- rescue EOFError
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
- ensure
130
- tf.unlink
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bup
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Baskinger