Module: Bitferry

Extended by:
Logging
Includes:
Logging
Defined in:
lib/bitferry.rb

Defined Under Namespace

Modules: Logging, Rclone, Restic Classes: Endpoint, Task, Volume

Constant Summary collapse

VERSION =
'0.0.1'
PATH_LIST_SEPARATOR =

Specify OS-specific path name list separator (such as in the $PATH environment variable)

windows? ? ';' : ':'
UNIX_SYSTEM_MOUNTS =

Match OS-specific system mount points (/dev /proc etc.) which normally should be omitted when scanning for Bitferry voulmes

%r!^/(dev|sys|proc|efi)!

Class Method Summary collapse

Methods included from Logging

log, log

Class Method Details

.commitObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/bitferry.rb', line 60

def self.commit
  log.info('committing changes')
  result = true
  modified = false
  Volume.registered.each do |volume|
    begin
      modified = true if volume.modified?
      volume.commit
    rescue IOError => e
       log.error(e.message)
       result = false
    end
  end
  if result
    log.info(modified ? 'changes committed' : 'commits skipped (no changes)')
  else
    log.warn('commit failure(s) reported')
  end
  result
end

.endpoint(root) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/bitferry.rb', line 112

def self.endpoint(root)
  case root
    when /^:(\w+):(.*)/
      volumes = Volume.lookup($1)
      volume = case volumes.size
        when 0 then raise ArgumentError, "no intact volume matching (partial) tag #{$1}"
        when 1 then volumes.first
        else
          tags = volumes.collect { |v| v.tag }.join(', ')
          raise ArgumentError, "multiple intact volumes matching (partial) tag #{$1}: #{tags}"
      end
      Endpoint::Bitferry.new(volume, $2)
    when /^(?:local)?:(.*)/ then Endpoint::Local.new($1)
    when /^(\w{2,}):(.*)/ then Endpoint::Rclone.new($1, $2)
    else Volume.endpoint(root)
  end
end

.environment_mountsObject

Return list of live user-provided mounts (mount points on *NIX and disk drives on Windows) which may contain Bitferry volumes Look for the $BITFERRY_PATH environment variable



148
149
150
# File 'lib/bitferry.rb', line 148

def self.environment_mounts
  ENV['BITFERRY_PATH'].split(PATH_LIST_SEPARATOR).collect { |path| File.directory?(path) ? path : nil }.compact rescue []
end

.optional(option, route) ⇒ Object



476
477
478
479
480
481
482
483
# File 'lib/bitferry.rb', line 476

def self.optional(option, route)
  case option
  when Array then option # Array is passed verbatim
  when '-' then nil # Disable adding any options with -
  when /^-/ then option.split(',') # Split comma-separated string into array --foo,bar --> [--foo, bar]
  else route.fetch(option) # Obtain array from the database
  end
end

.process(*tags) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/bitferry.rb', line 89

def self.process(*tags)
  log.info('processing tasks')
  tasks = Volume.intact.collect { |volume| volume.intact_tasks }.flatten.uniq
  if tags.empty?
    process = tasks
  else
    process = []
    tags.each do |tag|
      case (tasks = Task.match([tag], tasks)).size
        when 0 then log.warn("no tasks matching (partial) tag #{tag}")
        when 1 then process += tasks
        else
          tags = tasks.collect { |v| v.tag }.join(', ')
          raise ArgumentError, "multiple tasks matching (partial) tag #{tag}: #{tags}"
      end
    end
  end
  result = process.uniq.all? { |task| task.process }
  result ? log.info('tasks processed') : log.warn('task process failure(s) reported')
  result
end

.resetObject



82
83
84
85
86
# File 'lib/bitferry.rb', line 82

def self.reset
  log.info('resetting state')
  Volume.reset
  Task.reset
end

.restoreObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/bitferry.rb', line 39

def self.restore
  reset
  log.info('restoring volumes')
  result = true
  roots = (environment_mounts + system_mounts).uniq
  log.info("distilled volume search path: #{roots.join(', ')}")
  roots.each do |root|
    if File.exist?(File.join(root, Volume::STORAGE))
      log.info("trying to restore volume from #{root}")
      Volume.restore(root) rescue result = false
    end
  end
  if result
    log.info('volumes restored')
  else
    log.warn('volume restore failure(s) reported')
  end
  result
end

.simulate=(mode) ⇒ Object



133
# File 'lib/bitferry.rb', line 133

def self.simulate=(mode) @simulate = mode end

.simulate?Boolean

Returns:

  • (Boolean)


132
# File 'lib/bitferry.rb', line 132

def self.simulate? = @simulate

.system_mountsObject



164
165
166
# File 'lib/bitferry.rb', line 164

def self.system_mounts
  java.nio.file.FileSystems.getDefault.getFileStores.collect {|x| /^(.*)\s+\(.*\)$/.match(x.to_s)[1]}
end

.tagObject



36
# File 'lib/bitferry.rb', line 36

def self.tag = format('%08x', 2**32*rand)

.verbosityObject



137
# File 'lib/bitferry.rb', line 137

def self.verbosity = @verbosity

.verbosity=(mode) ⇒ Object



138
# File 'lib/bitferry.rb', line 138

def self.verbosity=(mode) @verbosity = mode end

.windows?Boolean

Return true if run in the real Windows environment (e.g. not in real *NIX or various emulation layers such as MSYS, Cygwin etc.)

Returns:

  • (Boolean)


142
143
144
# File 'lib/bitferry.rb', line 142

def self.windows?
  @windows ||= /^(mingw)/.match?(RbConfig::CONFIG['target_os']) # RubyInstaller's MRI, other MinGW-build MRI
end