Class: UPM::Tool

Inherits:
Object
  • Object
show all
Defined in:
lib/upm/tool.rb

Constant Summary collapse

COMMAND_HELP =
{
  "install"          => "install a package",
  "remove/uninstall" => "remove a package",
  "build"            => "compile a package from source and install it",
  "search"           => "using the fastest known API or service",
  "list"             => "list installed packages (or search their names if extra arguments are supplied)",
  "info"             => "show metadata about a package",
  "update/sync"      => "retrieve the latest package list or manifest",
  "upgrade"          => "install new versions of all packages",
  "pin"              => "pinning a package means it won't be automatically upgraded",
  "rollback"         => "revert to an earlier version of a package (including its dependencies)",
  "log"              => "show history of package installs",
  "packagers"        => "detect installed package managers, and pick which ones upm should wrap",
  "mirrors/sources"  => "manage remote repositories and mirrors",
  "verfiy"           => "verify the integrity of installed files",
  "clean"            => "clear out the local package cache",
  "monitor"          => "ad-hoc package manager for custom installations (like instmon)",
  "keys"             => "keyrings and package authentication",
  "default"          => "configure the action to take when no arguments are passed to 'upm' (defaults to 'os:update')",
}
ALIASES =
{
  "file"    => "files",
  "sync"    => "update",
  "sources" => "mirrors",
  "show"    => "info",
}
@@tools =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, &block) ⇒ Tool

Returns a new instance of Tool.



80
81
82
83
84
85
# File 'lib/upm/tool.rb', line 80

def initialize(name, &block)
  @name = name
  instance_eval(&block)

  @@tools[name] = self
end

Class Method Details

.current_os_namesObject



58
59
60
61
62
# File 'lib/upm/tool.rb', line 58

def self.current_os_names
  # ID=ubuntu
  # ID_LIKE=debian
  os_release.values_at("ID", "ID_LIKE").compact
end

.for_os(os_names = nil) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/upm/tool.rb', line 68

def self.for_os(os_names=nil)
  os_names = os_names ? [os_names].flatten : current_os_names

  if os_names.any?
    @@tools.find { |name, tool| os_names.any? { |name| tool.os.include? name } }.last
  else
    @@tools.find { |name, tool| File.which(tool.identifying_binary) }.last
  end
end

.nice_os_nameObject



64
65
66
# File 'lib/upm/tool.rb', line 64

def self.nice_os_name
  os_release.values_at("PRETTY_NAME", "NAME", "ID", "ID_LIKE").first
end

.os_releaseObject



48
49
50
51
52
53
54
55
56
# File 'lib/upm/tool.rb', line 48

def self.os_release
  @os_release ||= begin
    open("/etc/os-release") do |io|
      io.read.scan(/^(\w+)="?(.+?)"?$/)
    end.to_h
  rescue Errno::ENOENT
    {}
  end
end

.register_tools!Object



44
45
46
# File 'lib/upm/tool.rb', line 44

def self.register_tools!
  Dir["#{__dir__}/tools/*.rb"].each { |lib| require_relative(lib) }
end

.toolsObject



42
# File 'lib/upm/tool.rb', line 42

def self.tools; @@tools; end

Instance Method Details

#call_command(name, *args) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/upm/tool.rb', line 87

def call_command(name, *args)
  if block = (@cmds[name] || @cmds[ALIASES[name]])
    block.call args
  else
    puts "Command #{name} not supported in #{@name}"
  end
end

#command(name, shell_command = nil, root: false, paged: false, &block) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/upm/tool.rb', line 128

def command(name, shell_command=nil, root: false, paged: false, &block)
  @cmds ||= {}

  if block_given?
    @cmds[name] = block
  elsif shell_command
    if shell_command.is_a? String
      shell_command = shell_command.split
    elsif not shell_command.is_a? Array
      raise "Error: command argument must be a String or an Array; it was a #{cmd.class}"
    end

    @cmds[name] = proc { |args| run(*shell_command, *args, paged: paged) }
  end
end

#helpObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/upm/tool.rb', line 95

def help
  if osname = Tool.nice_os_name
    puts "    Detected OS: #{osname}"
  end

  puts "Package manager: #{@name}"
  puts
  puts "Available commands:"
  available = COMMAND_HELP.select do |name, desc|
    names = name.split("/")
    names.any? { |name| @cmds[name] }
  end

  max_width = available.map(&:first).map(&:size).max
  available.each do |name, desc|
    puts "  #{name.rjust(max_width)} | #{desc}"
  end
end

#identifying_binary(id_bin = nil) ⇒ Object

DSL methods



116
117
118
119
120
121
122
# File 'lib/upm/tool.rb', line 116

def identifying_binary(id_bin=nil)
  if id_bin 
    @id_bin = id_bin
  else
    @id_bin || @name
  end
end

#os(*names) ⇒ Object



144
145
146
# File 'lib/upm/tool.rb', line 144

def os(*names)
  names.any? ? @os = names : @os
end

#prefix(name) ⇒ Object



124
125
126
# File 'lib/upm/tool.rb', line 124

def prefix(name)
  @prefix = name
end


181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/upm/tool.rb', line 181

def print_files(*paths, include: nil, exclude: nil)
  lesspipe do |less|
    paths.each do |path|
      less.puts "<8>=== <11>#{path} <8>========".colorize
      open(path) do |io|
        enum = io.each_line
        enum = enum.grep(include) if include
        enum = enum.reject { |line| line[exclude] } if exclude
        enum.each { |line| less.puts line }
      end
      less.puts
    end
  end
end

#run(*args, root: false, paged: false, grep: nil) ⇒ Object

Helpers



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/upm/tool.rb', line 150

def run(*args, root: false, paged: false, grep: nil)
  args.unshift "sudo" if root

  if !paged and !grep
    system(*args)
  else

    IO.popen(args, err: [:child, :out]) do |command_io|
      
      if grep
        pattern = grep.is_a?(Regexp) ? grep.source : grep.to_s 
        grep_io = IO.popen(["grep", "--color=always", "-Ei", pattern], "w+")
        IO.copy_stream(command_io, grep_io)
        grep_io.close_write
        command_io = grep_io
      end

      if paged
        lesspipe do |less|
          IO.copy_stream(command_io, less)
        end
      else
        IO.copy_stream(command_io, STDOUT)
      end

    end

    $?.to_i == 0
  end
end