Class: Snapsync::Btrfs
- Inherits:
-
Object
show all
- Includes:
- Comparable
- Defined in:
- lib/snapsync/btrfs.rb
Defined Under Namespace
Classes: Error, UnexpectedBtrfsOutput
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(mountpoint) ⇒ Btrfs
Returns a new instance of Btrfs.
42
43
44
45
46
47
48
49
|
# File 'lib/snapsync/btrfs.rb', line 42
def initialize(mountpoint)
raise "Trying to create Btrfs wrapper on non-mountpoint #{mountpoint}" unless mountpoint.mountpoint?
Snapsync.debug "Creating Btrfs wrapper at #{mountpoint}"
@mountpoint = mountpoint
@subvolume_table = read_subvolume_table
end
|
Class Attribute Details
._mountpointCache ⇒ Hash
5
6
7
|
# File 'lib/snapsync/btrfs.rb', line 5
def _mountpointCache
@_mountpointCache
end
|
Instance Attribute Details
36
37
38
|
# File 'lib/snapsync/btrfs.rb', line 36
def mountpoint
@mountpoint
end
|
39
40
41
|
# File 'lib/snapsync/btrfs.rb', line 39
def subvolume_table
@subvolume_table
end
|
Class Method Details
.get(mountpoint) ⇒ Btrfs
53
54
55
56
57
58
59
60
61
|
# File 'lib/snapsync/btrfs.rb', line 53
def self.get(mountpoint)
mountpoint = mountpoint.findmnt
self._mountpointCache.fetch(mountpoint.to_s) do
btrfs = Btrfs.new mountpoint
self._mountpointCache[mountpoint.to_s] = btrfs
btrfs
end
end
|
Instance Method Details
#<=>(other) ⇒ Object
31
32
33
|
# File 'lib/snapsync/btrfs.rb', line 31
def <=>(other)
mountpoint.to_s <=> other.mountpoint.to_s
end
|
#btrfs_prog ⇒ Object
63
64
65
|
# File 'lib/snapsync/btrfs.rb', line 63
def btrfs_prog
ENV['BTRFS_PROG'] || 'btrfs'
end
|
#find_new(subvolume_dir, last_gen) {|a| ... } ⇒ Object
#find_new(subvolume_dir, last_gen) ⇒ #each
Facade for ‘btrfs subvolume find-new’
It computes what changed between a reference generation of a subvolume, and that subvolume’s current state
128
129
130
131
|
# File 'lib/snapsync/btrfs.rb', line 128
def find_new(subvolume_dir, last_gen, &block)
run('subvolume', 'find-new', subvolume_dir.to_s, last_gen.to_s).
each_line(&block)
end
|
#generation_of(path) ⇒ Integer
Facade for finding the generation of a subvolume using ‘btrfs show’
105
106
107
108
109
110
111
112
113
|
# File 'lib/snapsync/btrfs.rb', line 105
def generation_of(path)
info = run('subvolume', 'show', path.to_s)
if info =~ /Generation[^:]*:\s+(\d+)/
Integer($1)
else
raise UnexpectedBtrfsOutput, "unexpected output for 'btrfs subvolume show'," \
+" expected '#{info}' to contain a 'Generation:' line"
end
end
|
#popen(*args, mode: 'r', raise_on_error: true, **options) {|io| ... } ⇒ Object
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
A IO.popen-like API to btrfs subcommands
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/snapsync/btrfs.rb', line 71
def popen(*args, mode: 'r', raise_on_error: true, **options)
Snapsync.debug "Btrfs(\"#{mountpoint}\").popen: #{args}"
if @mountpoint.is_a? RemotePathname
proc = SSHPopen.new(@mountpoint, [btrfs_prog, *args], **options)
return yield(proc)
else
err_r, err_w = IO.pipe
begin
IO.popen([btrfs_prog, *args], err: err_w, mode: mode) do |io|
err_w.close
return yield(io)
end
if not $?.success?
raise Error.new, err_r.read.lines
end
ensure err_r.close
end
end
end
|
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
# File 'lib/snapsync/btrfs.rb', line 134
def read_subvolume_table
table = []
text = run('subvolume', 'list','-pcgquR', mountpoint.path_part)
text.each_line do |l|
item = SubvolumeMinimalInfo.new
l.gsub!('top level', 'top_level')
l = l.split
l.each_slice(2) do |kv|
k,v = kv
if v == '-'
v = nil
else
begin
v = Integer(v)
rescue
end
end
item.instance_variable_set '@'+k, v
end
table.push item
end
table
end
|
#run(*args, **options) ⇒ String
95
96
97
98
99
|
# File 'lib/snapsync/btrfs.rb', line 95
def run(*args, **options)
popen(*args, **options) do |io|
io.read.encode('utf-8', undef: :replace, invalid: :replace)
end
end
|
#subvolume_show(subvolume_dir) ⇒ Hash<String>
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/snapsync/btrfs.rb', line 163
def subvolume_show(subvolume_dir)
info = run('subvolume', 'show', subvolume_dir.path_part)
data = {}
data['absolute_dir'] = info.lines[0].strip
lines = info.lines[1..-1]
lines.each_index do |i|
l = lines[i]
k, _, v = l.partition ':'
k = k.strip.downcase.gsub ' ', '_'
if k == 'snapshot(s)'
data['snapshots'] = lines[i+1..-1].map do |s|
s.strip
end
break
else
data[k] = v.strip
end
end
data
end
|