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 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