ruaur 0.1.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 +7 -0
- data/bin/ruaur +201 -0
- data/lib/ruaur/aur.rb +263 -0
- data/lib/ruaur/error/aur_error.rb +5 -0
- data/lib/ruaur/error/failed_to_compile_error.rb +6 -0
- data/lib/ruaur/error/failed_to_download_error.rb +6 -0
- data/lib/ruaur/error/failed_to_extract_error.rb +6 -0
- data/lib/ruaur/error/missing_dependency_error.rb +6 -0
- data/lib/ruaur/error/package_not_found_error.rb +6 -0
- data/lib/ruaur/error/package_not_installed_error.rb +6 -0
- data/lib/ruaur/error/ruaur_already_running_error.rb +5 -0
- data/lib/ruaur/error.rb +11 -0
- data/lib/ruaur/package.rb +95 -0
- data/lib/ruaur/pacman.rb +124 -0
- data/lib/ruaur.rb +82 -0
- data/lib/string.rb +48 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 50ebe39558c3e6efd9953ae693863c8d7e7686c5
|
4
|
+
data.tar.gz: f4be7e20aa56a689686470120d08c4a82d6ef496
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 35750a58dd7ba7b56e899b47504db601d8c8d211b6c0464efd5e2b50471eacdc630196b3e47e2e670b78ffd6534cee85869f83f1106d2aee18695fc3b93a6072
|
7
|
+
data.tar.gz: da1963ce9bb15df155d8b012b74d1cca7cb6a24964607fb9623a46838ba2b5e4306a4f7b7916f41497aa1e221bf734273ddc80f554fdcb48c76943fa9ee5371b
|
data/bin/ruaur
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "ruaur"
|
5
|
+
require "string"
|
6
|
+
|
7
|
+
class RuAURExit
|
8
|
+
GOOD = 0
|
9
|
+
INVALID_OPTION = 1
|
10
|
+
INVALID_ARGUMENT = 2
|
11
|
+
MISSING_ARGUMENT = 3
|
12
|
+
INVALID_OPERATION = 4
|
13
|
+
MULTIPLE_OPERATIONS = 5
|
14
|
+
EXCEPTION = 6
|
15
|
+
end
|
16
|
+
|
17
|
+
class Operation
|
18
|
+
REMOVE = 1
|
19
|
+
SYNC = 2
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(args)
|
23
|
+
options = Hash.new
|
24
|
+
options["operation"] = nil
|
25
|
+
|
26
|
+
# Sync options
|
27
|
+
options["clean"] = false
|
28
|
+
options["noconfirm"] = false
|
29
|
+
options["search"] = false
|
30
|
+
options["upgrade"] = false
|
31
|
+
|
32
|
+
# Remove options
|
33
|
+
options["nosave"] = false
|
34
|
+
|
35
|
+
parser = OptionParser.new do |opts|
|
36
|
+
opts.banner =
|
37
|
+
"Usage: #{File.basename($0)} <operation> [OPTIONS] [pkgs]"
|
38
|
+
|
39
|
+
opts.on("", "OPERATIONS")
|
40
|
+
|
41
|
+
opts.on("-h", "--help", "Display this help message") do
|
42
|
+
puts opts
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("-R", "--remove", "Remove packages") do
|
47
|
+
if (options["operation"])
|
48
|
+
puts opts
|
49
|
+
exit RuAURExit::MULTIPLE_OPERATIONS
|
50
|
+
end
|
51
|
+
options["operation"] = Operation::REMOVE
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on("-S", "--sync", "Synchronize packages") do
|
55
|
+
if (options["operation"])
|
56
|
+
puts opts
|
57
|
+
exit RuAURExit::MULTIPLE_OPERATIONS
|
58
|
+
end
|
59
|
+
options["operation"] = Operation::SYNC
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("", "SYNC OPTIONS")
|
63
|
+
|
64
|
+
opts.on("-c", "--clean", "Remove packages from the cache") do
|
65
|
+
options["clean"] = true
|
66
|
+
end
|
67
|
+
|
68
|
+
opts.on(
|
69
|
+
"--noconfirm",
|
70
|
+
"Bypass any and all \"Are you sure?\" messages."
|
71
|
+
) do
|
72
|
+
options["noconfirm"] = true
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on(
|
76
|
+
"-s",
|
77
|
+
"--search",
|
78
|
+
"Search the sync database and AUR for packages"
|
79
|
+
) do
|
80
|
+
options["search"] = true
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-u", "--sysupgrade", "Upgrade all packages") do
|
84
|
+
options["upgrade"] = true
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on("", "REMOVE OPTIONS")
|
88
|
+
|
89
|
+
opts.on("-n", "--nosave", "Completely remove package") do
|
90
|
+
options["nosave"] = true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
begin
|
95
|
+
parser.parse!
|
96
|
+
rescue OptionParser::InvalidOption => e
|
97
|
+
puts e.message
|
98
|
+
puts parser
|
99
|
+
exit RuAURExit::INVALID_OPTION
|
100
|
+
rescue OptionParser::InvalidArgument => e
|
101
|
+
puts e.message
|
102
|
+
puts parser
|
103
|
+
exit RuAURExit::INVALID_ARGUMENT
|
104
|
+
rescue OptionParser::MissingArgument => e
|
105
|
+
puts e.message
|
106
|
+
puts parser
|
107
|
+
exit RuAURExit::MISSING_ARGUMENT
|
108
|
+
end
|
109
|
+
|
110
|
+
if (!validate(options))
|
111
|
+
puts parser
|
112
|
+
exit RuAURExit::INVALID_OPERATION
|
113
|
+
end
|
114
|
+
|
115
|
+
options["packages"] = args
|
116
|
+
|
117
|
+
return options
|
118
|
+
end
|
119
|
+
|
120
|
+
def validate(options)
|
121
|
+
case options["operation"]
|
122
|
+
when Operation::REMOVE
|
123
|
+
if (
|
124
|
+
options["clean"] ||
|
125
|
+
options["noconfirm"] ||
|
126
|
+
options["search"] ||
|
127
|
+
options["upgrade"]
|
128
|
+
)
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
when Operation::SYNC
|
132
|
+
return false if (options["nosave"])
|
133
|
+
|
134
|
+
if (options["clean"])
|
135
|
+
if (
|
136
|
+
options["noconfirm"] ||
|
137
|
+
options["search"] ||
|
138
|
+
options["upgrade"]
|
139
|
+
)
|
140
|
+
return false
|
141
|
+
end
|
142
|
+
elsif (options["noconfirm"])
|
143
|
+
if (
|
144
|
+
options["clean"] ||
|
145
|
+
options["search"] ||
|
146
|
+
options["upgrade"]
|
147
|
+
)
|
148
|
+
return false
|
149
|
+
end
|
150
|
+
elsif (options["search"])
|
151
|
+
if (
|
152
|
+
options["clean"] ||
|
153
|
+
options["noconfirm"] ||
|
154
|
+
options["upgrade"]
|
155
|
+
)
|
156
|
+
return false
|
157
|
+
end
|
158
|
+
elsif (options["upgrade"])
|
159
|
+
if (
|
160
|
+
options["clean"] ||
|
161
|
+
options["noconfirm"] ||
|
162
|
+
options["search"]
|
163
|
+
)
|
164
|
+
return false
|
165
|
+
end
|
166
|
+
end
|
167
|
+
else
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
|
171
|
+
return true
|
172
|
+
end
|
173
|
+
|
174
|
+
# Parse CLI args
|
175
|
+
options = parse(ARGV)
|
176
|
+
|
177
|
+
begin
|
178
|
+
ruaur = RuAUR.new
|
179
|
+
|
180
|
+
case options["operation"]
|
181
|
+
when Operation::REMOVE
|
182
|
+
ruaur.remove(options["packages"], options["nosave"])
|
183
|
+
when Operation::SYNC
|
184
|
+
if (options["clean"])
|
185
|
+
ruaur.clean(options["noconfirm"])
|
186
|
+
elsif (options["search"])
|
187
|
+
puts ruaur.search(options["packages"].join(" "))
|
188
|
+
elsif (options["upgrade"])
|
189
|
+
ruaur.upgrade(options["noconfirm"])
|
190
|
+
else
|
191
|
+
ruaur.install(options["packages"], options["noconfirm"])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
exit RuAURExit::GOOD
|
195
|
+
rescue RuAUR::Error => e
|
196
|
+
puts e.message.red
|
197
|
+
exit RuAURExit::EXCEPTION
|
198
|
+
rescue Interrupt => e
|
199
|
+
# ^C
|
200
|
+
puts
|
201
|
+
end
|
data/lib/ruaur/aur.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
require "archive/tar/minitar"
|
2
|
+
require "fileutils"
|
3
|
+
require "io/wait"
|
4
|
+
require "json"
|
5
|
+
require "scoobydoo"
|
6
|
+
require "typhoeus"
|
7
|
+
require "zlib"
|
8
|
+
|
9
|
+
class RuAUR::AUR
|
10
|
+
def clean
|
11
|
+
puts "Cleaning AUR cache...".white
|
12
|
+
Dir.chdir(@cache) do
|
13
|
+
FileUtils.rm_rf(Dir["*"])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def compile(package)
|
18
|
+
puts "Compiling #{package.name}...".white
|
19
|
+
if (Process.uid == 0)
|
20
|
+
system("chown -R nobody:nobody .")
|
21
|
+
system("su -s /bin/sh nobody -c \"makepkg -sr\"")
|
22
|
+
else
|
23
|
+
system("makepkg -sr")
|
24
|
+
end
|
25
|
+
|
26
|
+
compiled = Dir["#{package.name}*.pkg.tar.xz"]
|
27
|
+
if (compiled.empty?)
|
28
|
+
raise RuAUR::Error::FailedToCompileError.new(package.name)
|
29
|
+
end
|
30
|
+
|
31
|
+
return compiled
|
32
|
+
end
|
33
|
+
private :compile
|
34
|
+
|
35
|
+
def download(package)
|
36
|
+
FileUtils.rm_f(Dir["#{package.name}.tar.gz*"])
|
37
|
+
|
38
|
+
puts "Downloading #{package.name}...".white
|
39
|
+
tarball(package.name, package.url, "#{package.name}.tar.gz")
|
40
|
+
|
41
|
+
tgz = Pathname.new("#{package.name}.tar.gz").expand_path
|
42
|
+
if (!tgz.exist?)
|
43
|
+
raise RuAUR::Error::FailedToDownloadError.new(
|
44
|
+
package.name
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
private :download
|
49
|
+
|
50
|
+
def edit_pkgbuild(package, noconfirm = false)
|
51
|
+
return false if (noconfirm)
|
52
|
+
|
53
|
+
print "Do you want to edit the PKGBUILD y/[n]/q?: "
|
54
|
+
answer = nil
|
55
|
+
while (answer.nil?)
|
56
|
+
begin
|
57
|
+
system("stty raw -echo")
|
58
|
+
if ($stdin.ready?)
|
59
|
+
answer = $stdin.getc
|
60
|
+
else
|
61
|
+
sleep 0.1
|
62
|
+
end
|
63
|
+
ensure
|
64
|
+
system("stty -raw echo")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
puts
|
68
|
+
|
69
|
+
case answer
|
70
|
+
when "y", "Y"
|
71
|
+
editor = ENV["EDITOR"]
|
72
|
+
editor = ScoobyDoo.where_are_you("vim") if (editor.nil?)
|
73
|
+
editor = ScoobyDoo.where_are_you("vi") if (editor.nil?)
|
74
|
+
system("#{editor} PKGBUILD")
|
75
|
+
when "q", "Q", "\x03"
|
76
|
+
# Quit or ^C
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
private :edit_pkgbuild
|
82
|
+
|
83
|
+
def extract(package)
|
84
|
+
FileUtils.rm_rf(package.name)
|
85
|
+
|
86
|
+
puts "Extracting #{package.name}...".white
|
87
|
+
File.open("#{package.name}.tar.gz", "rb") do |tgz|
|
88
|
+
tar = Zlib::GzipReader.new(tgz)
|
89
|
+
Archive::Tar::Minitar.unpack(tar, ".")
|
90
|
+
end
|
91
|
+
FileUtils.rm_f("pax_global_header")
|
92
|
+
|
93
|
+
dir = Pathname.new(package.name).expand_path
|
94
|
+
if (!dir.exist? || !dir.directory?)
|
95
|
+
raise RuAUR::Error::FailedToExtractError.new(package.name)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
private :extract
|
99
|
+
|
100
|
+
def find_upgrades
|
101
|
+
puts "Checking for AUR updates...".white
|
102
|
+
|
103
|
+
upgrades = Hash.new
|
104
|
+
multiinfo(@installed.keys).each do |package|
|
105
|
+
if (
|
106
|
+
@installed.has_key?(package.name) &&
|
107
|
+
package.newer?(@installed[package.name])
|
108
|
+
)
|
109
|
+
upgrades[package.name] = [
|
110
|
+
@installed[package.name],
|
111
|
+
package.version
|
112
|
+
]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
return upgrades
|
117
|
+
end
|
118
|
+
private :find_upgrades
|
119
|
+
|
120
|
+
def info(package)
|
121
|
+
return nil if (package.nil? || package.empty?)
|
122
|
+
|
123
|
+
query = "type=info&arg=#{package}"
|
124
|
+
body = JSON.parse(Typhoeus.get("#{@rpc_url}?#{query}").body)
|
125
|
+
|
126
|
+
if (body["type"] == "error")
|
127
|
+
raise RuAUR::Error::AURError.new(body["results"])
|
128
|
+
end
|
129
|
+
|
130
|
+
return nil if (body["results"].empty?)
|
131
|
+
return RuAUR::Package.new(body["results"])
|
132
|
+
end
|
133
|
+
|
134
|
+
def initialize(pacman, cache = "/tmp/ruaur-#{ENV["USER"]}")
|
135
|
+
@cache = Pathname.new(cache).expand_path
|
136
|
+
FileUtils.mkdir_p(@cache)
|
137
|
+
@installed = pacman.query_aur
|
138
|
+
@pacman = pacman
|
139
|
+
@rpc_url = "https://aur.archlinux.org/rpc.php"
|
140
|
+
end
|
141
|
+
|
142
|
+
def install(pkg_name, noconfirm = false)
|
143
|
+
package = info(pkg_name)
|
144
|
+
|
145
|
+
if (package.nil?)
|
146
|
+
raise RuAUR::Error::PackageNotFoundError.new(pkg_name)
|
147
|
+
end
|
148
|
+
|
149
|
+
if (
|
150
|
+
@installed.include?(pkg_name) &&
|
151
|
+
!package.newer?(@installed[pkg_name])
|
152
|
+
)
|
153
|
+
puts "Already installed: #{pkg_name}".yellow
|
154
|
+
return
|
155
|
+
end
|
156
|
+
|
157
|
+
Dir.chdir(@cache) do
|
158
|
+
download(package)
|
159
|
+
extract(package)
|
160
|
+
end
|
161
|
+
Dir.chdir("#{@cache}/#{package.name}") do
|
162
|
+
return if (edit_pkgbuild(package, noconfirm))
|
163
|
+
install_dependencies(package, noconfirm)
|
164
|
+
compiled = compile(package)
|
165
|
+
@pacman.install_local(compiled, noconfirm)
|
166
|
+
end
|
167
|
+
|
168
|
+
@installed.merge!(@pacman.query_aur(pkg_name))
|
169
|
+
end
|
170
|
+
|
171
|
+
def install_dependencies(package, noconfirm)
|
172
|
+
pkgbuild = File.read("PKGBUILD")
|
173
|
+
|
174
|
+
pkgbuild.match(/^depends\=\(([^\)]+)\)/m) do |match|
|
175
|
+
match.captures.each do |cap|
|
176
|
+
cap.gsub(/\n/, " ").scan(/[^' ]+/) do |scan|
|
177
|
+
dep = scan.gsub(/(\<|\=|\>).*$/, "")
|
178
|
+
if (!@installed.has_key?(dep))
|
179
|
+
puts "Installing dependency: #{dep}".purple
|
180
|
+
if (@pacman.exist?(dep))
|
181
|
+
@pacman.install(dep, noconfirm)
|
182
|
+
else
|
183
|
+
install(dep, noconfirm)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
private :install_dependencies
|
191
|
+
|
192
|
+
def multiinfo(pkgs)
|
193
|
+
results = Array.new
|
194
|
+
return results if (pkgs.nil? || pkgs.empty?)
|
195
|
+
|
196
|
+
query = "type=multiinfo&arg[]=#{pkgs.join("&arg[]=")}"
|
197
|
+
body = JSON.parse(Typhoeus.get("#{@rpc_url}?#{query}").body)
|
198
|
+
|
199
|
+
if (body["type"] == "error")
|
200
|
+
raise RuAUR::Error::AURError.new(body["results"])
|
201
|
+
end
|
202
|
+
|
203
|
+
body["results"].each do |result|
|
204
|
+
results.push(RuAUR::Package.new(result))
|
205
|
+
end
|
206
|
+
return results.sort
|
207
|
+
end
|
208
|
+
|
209
|
+
def search(string)
|
210
|
+
results = Array.new
|
211
|
+
return results if (string.nil? || string.empty?)
|
212
|
+
|
213
|
+
query = "type=search&arg=#{string}"
|
214
|
+
body = JSON.parse(Typhoeus.get("#{@rpc_url}?#{query}").body)
|
215
|
+
|
216
|
+
if (body["type"] == "error")
|
217
|
+
raise RuAUR::Error::AURError.new(body["results"])
|
218
|
+
end
|
219
|
+
|
220
|
+
body["results"].each do |result|
|
221
|
+
results.push(RuAUR::Package.new(result))
|
222
|
+
end
|
223
|
+
|
224
|
+
results.each do |package|
|
225
|
+
if (@installed.has_key?(package.name))
|
226
|
+
package.installed(@installed[package.name])
|
227
|
+
end
|
228
|
+
end
|
229
|
+
return results.sort
|
230
|
+
end
|
231
|
+
|
232
|
+
def tarball(name, url, file)
|
233
|
+
if (url.nil? || url.empty? || file.nil? || file.empty?)
|
234
|
+
return nil
|
235
|
+
end
|
236
|
+
|
237
|
+
tgz = File.open(file, "wb")
|
238
|
+
request = Typhoeus::Request.new(url)
|
239
|
+
request.on_headers do |response|
|
240
|
+
if (response.code != 200)
|
241
|
+
raise RuAUR::Error::FailedToDownloadError.new(name)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
request.on_body do |chunk|
|
245
|
+
tgz.write(chunk)
|
246
|
+
end
|
247
|
+
request.on_complete do
|
248
|
+
tgz.close
|
249
|
+
end
|
250
|
+
request.run
|
251
|
+
end
|
252
|
+
private :tarball
|
253
|
+
|
254
|
+
def upgrade(noconfirm = false)
|
255
|
+
find_upgrades.each do |pkg_name, versions|
|
256
|
+
old, new = versions
|
257
|
+
|
258
|
+
puts "Upgrading #{pkg_name}...".white
|
259
|
+
puts "#{old.red} -> #{new.green}"
|
260
|
+
install(pkg_name, noconfirm)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
data/lib/ruaur/error.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
class RuAUR::Error < RuntimeError
|
2
|
+
end
|
3
|
+
|
4
|
+
require "ruaur/error/aur_error"
|
5
|
+
require "ruaur/error/failed_to_compile_error"
|
6
|
+
require "ruaur/error/failed_to_download_error"
|
7
|
+
require "ruaur/error/failed_to_extract_error"
|
8
|
+
require "ruaur/error/missing_dependency_error"
|
9
|
+
require "ruaur/error/package_not_found_error"
|
10
|
+
require "ruaur/error/package_not_installed_error"
|
11
|
+
require "ruaur/error/ruaur_already_running_error"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require "string"
|
2
|
+
|
3
|
+
class RuAUR::Package
|
4
|
+
attr_accessor :description
|
5
|
+
attr_accessor :installed
|
6
|
+
attr_accessor :json
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :repo
|
9
|
+
attr_accessor :url
|
10
|
+
attr_accessor :version
|
11
|
+
attr_accessor :votes
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
if (self.name.downcase == other.name.downcase)
|
15
|
+
self_version = self.version.split(/\D+/).map(&:to_i)
|
16
|
+
other_version = self.version.split(/\D+/).map(&:to_i)
|
17
|
+
|
18
|
+
[self_version.size, other_version.size].max.times do |i|
|
19
|
+
cmp = self_version[i] <=> other_version[i]
|
20
|
+
return cmp if (cmp != 0)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
return (self.name.downcase <=> other.name.downcase)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(json, repo = "aur")
|
27
|
+
@description = json["Description"]
|
28
|
+
@installed = nil
|
29
|
+
@json = json
|
30
|
+
@name = json["Name"]
|
31
|
+
@repo = repo
|
32
|
+
if (json["URLPath"])
|
33
|
+
@url = "https://aur.archlinux.org#{json["URLPath"]}"
|
34
|
+
else
|
35
|
+
@url = nil
|
36
|
+
end
|
37
|
+
@version = json["Version"]
|
38
|
+
@votes = nil
|
39
|
+
@votes = "(#{json["NumVotes"]})" if (json["NumVotes"])
|
40
|
+
end
|
41
|
+
|
42
|
+
def installed(version = nil)
|
43
|
+
@installed = version if (version)
|
44
|
+
@installed = @version if (version.nil?)
|
45
|
+
end
|
46
|
+
|
47
|
+
def newer?(ver)
|
48
|
+
self_version = @version.split(/\D+/).map(&:to_i)
|
49
|
+
other_version = ver.split(/\D+/).map(&:to_i)
|
50
|
+
|
51
|
+
[self_version.size, other_version.size].max.times do |i|
|
52
|
+
if (self_version[i] > other_version[i])
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
def older?(version)
|
60
|
+
self_version = @version.split(/\D+/).map(&:to_i)
|
61
|
+
other_version = version.split(/\D+/).map(&:to_i)
|
62
|
+
|
63
|
+
[self_version.size, other_version.size].max.times do |i|
|
64
|
+
if (self_version[i] < other_version[i])
|
65
|
+
return true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
def tarball(file)
|
72
|
+
return RuAUR::AUR.tarball(@url, file)
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
out = Array.new
|
77
|
+
header = Array.new
|
78
|
+
|
79
|
+
header.push("#{@repo.blue}#{"/".blue}#{@name.cyan}")
|
80
|
+
if (@installed && newer?(@installed))
|
81
|
+
header.push(@installed.red)
|
82
|
+
header.push("->")
|
83
|
+
end
|
84
|
+
header.push(@version.green)
|
85
|
+
header.push(@votes.white) if (@votes)
|
86
|
+
header.push("[installed]".purple) if (@installed)
|
87
|
+
out.push(header.join(" "))
|
88
|
+
|
89
|
+
@description.word_wrap.each_line do |line|
|
90
|
+
out.push(" #{line.rstrip}")
|
91
|
+
end
|
92
|
+
|
93
|
+
return out.join("\n")
|
94
|
+
end
|
95
|
+
end
|
data/lib/ruaur/pacman.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
class RuAUR::Pacman
|
2
|
+
def clean(noconfirm = false)
|
3
|
+
puts "Cleaning pacman cache...".white
|
4
|
+
system("sudo #{@pac_clr} -Sc") if (!noconfirm)
|
5
|
+
system("sudo #{@pac_clr} -Sc --noconfirm") if (noconfirm)
|
6
|
+
end
|
7
|
+
|
8
|
+
def exist?(pkg_name)
|
9
|
+
return !%x(#{@pac_noclr} -Ss "^#{pkg_name}$").empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@pac_noclr = "pacman --color=never"
|
14
|
+
@pac_clr = "pacman --color=always"
|
15
|
+
@installed = query
|
16
|
+
end
|
17
|
+
|
18
|
+
def install(pkg_name, noconfirm = false)
|
19
|
+
if (@installed.include?(pkg_name))
|
20
|
+
puts "Already installed: #{pkg_name}".yellow
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "Installing #{pkg_name}...".white
|
25
|
+
if (!noconfirm)
|
26
|
+
system("sudo #{@pac_clr} -S #{pkg_name} --needed")
|
27
|
+
else
|
28
|
+
system(
|
29
|
+
"sudo #{@pac_clr} -S #{pkg_name} --needed --noconfirm"
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
@installed.merge!(query(pkg_name))
|
34
|
+
end
|
35
|
+
|
36
|
+
def install_local(pkgs, noconfirm = false)
|
37
|
+
pkgs.each do |pkg|
|
38
|
+
puts "Installing #{pkg}...".white
|
39
|
+
if (!noconfirm)
|
40
|
+
system("sudo #{@pac_clr} -U #{pkg}") if (!noconfirm)
|
41
|
+
else
|
42
|
+
system("sudo #{@pac_clr} -U #{pkg} --noconfirm")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def query(pkg_name = "")
|
48
|
+
results = Hash.new
|
49
|
+
%x(#{@pac_noclr} -Q #{pkg_name}).split("\n").map do |line|
|
50
|
+
line = line.split
|
51
|
+
results[line[0]] = line[1]
|
52
|
+
end
|
53
|
+
return results
|
54
|
+
end
|
55
|
+
|
56
|
+
def query_aur(pkg_name = "")
|
57
|
+
community = Pathname.new(
|
58
|
+
"/var/lib/pacman/sync/community"
|
59
|
+
).expand_path
|
60
|
+
|
61
|
+
results = Hash.new
|
62
|
+
%x(#{@pac_noclr} -Qm #{pkg_name}).split("\n").delete_if do |p|
|
63
|
+
# Skip packages in community
|
64
|
+
Dir["#{community}/#{p.split.join("-")}"].any?
|
65
|
+
end.map do |line|
|
66
|
+
line = line.split
|
67
|
+
results[line[0]] = line[1]
|
68
|
+
end
|
69
|
+
return results
|
70
|
+
end
|
71
|
+
|
72
|
+
def remove(pkg_names, nosave = false)
|
73
|
+
puts "Removing #{pkg_names.join(" ")}...".white
|
74
|
+
if (!nosave)
|
75
|
+
system("sudo #{@pac_clr} -R #{pkg_names.join(" ")}")
|
76
|
+
else
|
77
|
+
system("sudo #{@pac_clr} -Rn #{pkg_names.join(" ")}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def search(pkg_names)
|
82
|
+
results = Array.new
|
83
|
+
return results if (pkg_names.nil? || pkg_names.empty?)
|
84
|
+
|
85
|
+
%x(#{@pac_noclr} -Ss #{pkg_names}).each_line do |line|
|
86
|
+
reg = "^([^\/ ]+)\/([^ ]+) ([^ ]+)( .*)?$"
|
87
|
+
match = line.match(/#{reg}/)
|
88
|
+
if (match)
|
89
|
+
repo, name, version, trailing = match.captures
|
90
|
+
repo.strip!
|
91
|
+
name.strip!
|
92
|
+
version.strip!
|
93
|
+
trailing = "" if (trailing.nil?)
|
94
|
+
trailing.strip!
|
95
|
+
|
96
|
+
results.push(
|
97
|
+
RuAUR::Package.new(
|
98
|
+
{
|
99
|
+
"Description" => "",
|
100
|
+
"Name" => name,
|
101
|
+
"NumVotes" => nil,
|
102
|
+
"URLPath" => nil,
|
103
|
+
"Version" => version
|
104
|
+
},
|
105
|
+
repo
|
106
|
+
)
|
107
|
+
)
|
108
|
+
if (trailing.include?("[installed]"))
|
109
|
+
results.last.installed
|
110
|
+
end
|
111
|
+
elsif (results.any?)
|
112
|
+
results.last.description += " #{line.strip}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
return results
|
117
|
+
end
|
118
|
+
|
119
|
+
def upgrade(noconfirm = false)
|
120
|
+
puts "Updating...".white
|
121
|
+
system("sudo #{@pac_clr} -Syyu") if (!noconfirm)
|
122
|
+
system("sudo #{@pac_clr} -Syyu --noconfirm") if (noconfirm)
|
123
|
+
end
|
124
|
+
end
|
data/lib/ruaur.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "scoobydoo"
|
3
|
+
|
4
|
+
class RuAUR
|
5
|
+
def check_and_lock
|
6
|
+
if (@lock.exist?)
|
7
|
+
raise RuAUR::Error::RuAURAlreadyRunningError.new
|
8
|
+
end
|
9
|
+
|
10
|
+
FileUtils.touch(@lock)
|
11
|
+
end
|
12
|
+
private :check_and_lock
|
13
|
+
|
14
|
+
def clean(noconfirm)
|
15
|
+
@pacman.clean(noconfirm)
|
16
|
+
@aur.clean
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
[
|
21
|
+
"makepkg",
|
22
|
+
"pacman",
|
23
|
+
"su",
|
24
|
+
"sudo"
|
25
|
+
].each do |dep|
|
26
|
+
if (ScoobyDoo.where_are_you(dep).nil?)
|
27
|
+
raise RuAUR::Error::MissingDependencyError.new(dep)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
@pacman = RuAUR::Pacman.new
|
32
|
+
@aur = RuAUR::AUR.new(@pacman)
|
33
|
+
@lock = Pathname.new("/tmp/ruaur.lock").expand_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def install(pkg_names, noconfirm = false)
|
37
|
+
if (pkg_names.nil? || pkg_names.empty?)
|
38
|
+
raise RuAUR::Error::PackageNotFoundError.new
|
39
|
+
end
|
40
|
+
|
41
|
+
check_and_lock
|
42
|
+
|
43
|
+
pkg_names.each do |pkg_name|
|
44
|
+
if (@pacman.exist?(pkg_name))
|
45
|
+
@pacman.install(pkg_name, noconfirm)
|
46
|
+
else
|
47
|
+
@aur.install(pkg_name, noconfirm)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
unlock
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove(pkg_names, nosave = false)
|
55
|
+
check_and_lock
|
56
|
+
@pacman.remove(pkg_names, nosave)
|
57
|
+
ensure
|
58
|
+
unlock
|
59
|
+
end
|
60
|
+
|
61
|
+
def search(string)
|
62
|
+
return @pacman.search(string).concat(@aur.search(string))
|
63
|
+
end
|
64
|
+
|
65
|
+
def unlock
|
66
|
+
FileUtils.rm_f(@lock)
|
67
|
+
end
|
68
|
+
private :unlock
|
69
|
+
|
70
|
+
def upgrade(noconfirm = false)
|
71
|
+
check_and_lock
|
72
|
+
@pacman.upgrade(noconfirm)
|
73
|
+
@aur.upgrade(noconfirm)
|
74
|
+
ensure
|
75
|
+
unlock
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
require "ruaur/aur"
|
80
|
+
require "ruaur/error"
|
81
|
+
require "ruaur/package"
|
82
|
+
require "ruaur/pacman"
|
data/lib/string.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Redefine String class to allow for colorizing, rsplit, and word wrap
|
2
|
+
class String
|
3
|
+
def black
|
4
|
+
return colorize(30)
|
5
|
+
end
|
6
|
+
|
7
|
+
def blue
|
8
|
+
return colorize(34)
|
9
|
+
end
|
10
|
+
|
11
|
+
def colorize(color)
|
12
|
+
return "\e[#{color}m#{self}\e[0m"
|
13
|
+
end
|
14
|
+
|
15
|
+
def cyan
|
16
|
+
return colorize(36)
|
17
|
+
end
|
18
|
+
|
19
|
+
def green
|
20
|
+
return colorize(32)
|
21
|
+
end
|
22
|
+
|
23
|
+
def purple
|
24
|
+
return colorize(35)
|
25
|
+
end
|
26
|
+
|
27
|
+
def red
|
28
|
+
return colorize(31)
|
29
|
+
end
|
30
|
+
|
31
|
+
def rsplit(pattern)
|
32
|
+
ret = rpartition(pattern)
|
33
|
+
ret.delete_at(1)
|
34
|
+
return ret
|
35
|
+
end
|
36
|
+
|
37
|
+
def white
|
38
|
+
return colorize(37)
|
39
|
+
end
|
40
|
+
|
41
|
+
def word_wrap(width = 70)
|
42
|
+
return scan(/\S.{0,#{width}}\S(?=\s|$)|\S+/).join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
def yellow
|
46
|
+
return colorize(33)
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruaur
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Miles Whittaker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: archive-tar-minitar
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.5'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.5.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.5'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.5.2
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: scoobydoo
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.1'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.1.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.1'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.1.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: typhoeus
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0.8'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.8.0
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.8'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 0.8.0
|
73
|
+
description: RuAUR is a Ruby gem that allows searching and installing packages from
|
74
|
+
the Pacman sync database as well as the Arch User Repository (AUR).
|
75
|
+
email: mjwhitta@gmail.com
|
76
|
+
executables:
|
77
|
+
- ruaur
|
78
|
+
extensions: []
|
79
|
+
extra_rdoc_files: []
|
80
|
+
files:
|
81
|
+
- bin/ruaur
|
82
|
+
- lib/ruaur.rb
|
83
|
+
- lib/ruaur/aur.rb
|
84
|
+
- lib/ruaur/error.rb
|
85
|
+
- lib/ruaur/error/aur_error.rb
|
86
|
+
- lib/ruaur/error/failed_to_compile_error.rb
|
87
|
+
- lib/ruaur/error/failed_to_download_error.rb
|
88
|
+
- lib/ruaur/error/failed_to_extract_error.rb
|
89
|
+
- lib/ruaur/error/missing_dependency_error.rb
|
90
|
+
- lib/ruaur/error/package_not_found_error.rb
|
91
|
+
- lib/ruaur/error/package_not_installed_error.rb
|
92
|
+
- lib/ruaur/error/ruaur_already_running_error.rb
|
93
|
+
- lib/ruaur/package.rb
|
94
|
+
- lib/ruaur/pacman.rb
|
95
|
+
- lib/string.rb
|
96
|
+
homepage: https://mjwhitta.github.io/ruaur
|
97
|
+
licenses:
|
98
|
+
- GPL-3.0
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.4.5.1
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Can search and install packages for Arch Linux
|
120
|
+
test_files: []
|