aur.rb 0.1.0 → 0.2.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 +4 -4
- data/ChangeLog.md +136 -2
- data/LICENSE.txt +1 -1
- data/README.md +21 -1
- data/Rakefile +7 -10
- data/TODO.md +69 -0
- data/aur.rb.gemspec +1 -0
- data/bin/aur.rb +6 -0
- data/lib/aur.rb +43 -1853
- data/lib/aur/aur_rpc.rb +178 -0
- data/lib/aur/cli.rb +334 -0
- data/lib/aur/config.rb +330 -0
- data/lib/aur/db.rb +328 -0
- data/lib/aur/devtools.rb +258 -0
- data/lib/aur/helpers.rb +56 -0
- data/lib/aur/install_packages.rb +158 -0
- data/lib/aur/load_config.rb +5 -0
- data/lib/aur/makepkg.rb +445 -0
- data/lib/aur/no_load_config.rb +5 -0
- data/lib/aur/packages.rb +599 -0
- data/lib/aur/repos.rb +343 -0
- data/lib/aur/version.rb +1 -1
- data/lib/aur/versions.rb +186 -0
- metadata +22 -5
data/lib/aur/makepkg.rb
ADDED
@@ -0,0 +1,445 @@
|
|
1
|
+
require 'aur/config'
|
2
|
+
require 'aur/devtools'
|
3
|
+
require 'aur/packages'
|
4
|
+
require 'uri'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
module Archlinux
|
8
|
+
# this is a get class; it should respond to update and clone
|
9
|
+
class Git
|
10
|
+
extend CreateHelper
|
11
|
+
attr_accessor :dir, :config, :logdir
|
12
|
+
attr_writer :url
|
13
|
+
|
14
|
+
def initialize(dir, url: nil, logdir: nil, config: Archlinux.config)
|
15
|
+
@dir=Pathname.new(dir)
|
16
|
+
@url=url
|
17
|
+
@config=config
|
18
|
+
@logdir=logdir
|
19
|
+
end
|
20
|
+
|
21
|
+
def url
|
22
|
+
url=URI.parse(@url)
|
23
|
+
url.relative? ? @config[:aur_url]+@url.to_s+".git" : url
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(*args,**opts,&b)
|
27
|
+
opts[:method]||=:sh
|
28
|
+
@dir.chdir do
|
29
|
+
@config.launch(:git, *args, **opts, &b)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# callbacks called by makepkg
|
34
|
+
def done_view
|
35
|
+
call('branch', '-f', 'aur_view', 'HEAD')
|
36
|
+
end
|
37
|
+
def done_build
|
38
|
+
call('branch', '-f', 'aur_build', 'HEAD')
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_patch(logdir)
|
42
|
+
(logdir+"#{@dir.basename}").on_ln_s(@dir.realpath, rm: :symlink)
|
43
|
+
if call("rev-parse", "--verify", "aur_view", method: :run_success, quiet: true)
|
44
|
+
SH::VirtualFile.new("orderfile", "PKGBUILD").create(true) do |tmp|
|
45
|
+
patch=call("diff", "-O#{tmp}", "aur_view", "HEAD", method: :run_simple)
|
46
|
+
(logdir+"#{@dir.basename}.patch").write(patch) unless patch.empty?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def do_update
|
52
|
+
# we need to hard reset, because vercmp may have changed our PKGBUILD
|
53
|
+
# todo: only reset when there is an update?
|
54
|
+
# lets try with a theirs merge strat
|
55
|
+
# call("reset", "--hard")
|
56
|
+
# -> still does not work: error: Your local changes to the following files would be overwritten by merge: PKGBUILD
|
57
|
+
## suc, _r=call("pull", "-X", "theirs")
|
58
|
+
call("reset", "--hard")
|
59
|
+
suc, _r=call("pull")
|
60
|
+
suc
|
61
|
+
end
|
62
|
+
|
63
|
+
def do_clone(url)
|
64
|
+
#we cannot call 'call' here because the folder does not yet exist
|
65
|
+
suc, _r=@config.launch(:git, "clone", url, @dir, method: :sh)
|
66
|
+
suc
|
67
|
+
end
|
68
|
+
|
69
|
+
def update(logdir: nil)
|
70
|
+
if do_update
|
71
|
+
write_patch(logdir) if logdir
|
72
|
+
else
|
73
|
+
SH.logger.error("Error in updating #{@dir}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def clone(url: self.url, logdir: nil)
|
78
|
+
if do_clone(url)
|
79
|
+
(logdir+"!#{@dir.basename}").on_ln_s(@dir.realpath) if logdir
|
80
|
+
else
|
81
|
+
SH.logger.error("Error in cloning #{url} to #{@dir}")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
module MakepkgCommon
|
87
|
+
#functions common to Makepkg and MakepkgList
|
88
|
+
|
89
|
+
def add_to_db(db=@config.db, force_sign: false)
|
90
|
+
unless db.is_a?(DB)
|
91
|
+
SH.logger.error "Bad database #{db}, can't add to database"
|
92
|
+
else
|
93
|
+
db.add(*list.select {|l| r=l.exist?; SH.logger.warn "Package #{l} not built, not adding to the db #{db.repo_name}" unless r; r}, force_sign: force_sign)
|
94
|
+
true #do return false if there were errors
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
class Makepkg
|
101
|
+
extend CreateHelper
|
102
|
+
include MakepkgCommon
|
103
|
+
attr_accessor :dir, :base, :env, :config, :asdeps
|
104
|
+
attr_writer :get_pkg
|
105
|
+
|
106
|
+
def initialize(dir, config: Archlinux.config, env: {}, asdeps: false)
|
107
|
+
@dir=Pathname.new(dir)
|
108
|
+
@base=@dir.basename #the corresponding pkgbase
|
109
|
+
@config=config
|
110
|
+
@env=env
|
111
|
+
@asdeps=asdeps
|
112
|
+
db=@config.db
|
113
|
+
@env['PKGDEST']=db.dir.to_s if db
|
114
|
+
end
|
115
|
+
|
116
|
+
# should respond to clone, update
|
117
|
+
# and optionally done_view, done_build
|
118
|
+
def get_pkg
|
119
|
+
#@get_pkg||=@config[:default_get_class].new(@dir, url: name, config: @config)
|
120
|
+
@get_pkg ||= Archlinux.create_class(@config[:default_get_class], @dir, url: name, config: @config)
|
121
|
+
end
|
122
|
+
|
123
|
+
def name
|
124
|
+
@base.to_s
|
125
|
+
end
|
126
|
+
|
127
|
+
def pkgbuild
|
128
|
+
@dir+"PKGBUILD"
|
129
|
+
end
|
130
|
+
|
131
|
+
def exist?
|
132
|
+
pkgbuild.exist?
|
133
|
+
end
|
134
|
+
|
135
|
+
def raw_call(*args, method: :run_simple, **opts)
|
136
|
+
@config.launch(:makepkg, *args, **opts) do |*args, **opts|
|
137
|
+
@dir.chdir do
|
138
|
+
SH.public_send(method, @env, *args, **opts)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# raw call to makepkg
|
144
|
+
def makepkg(*args, **opts)
|
145
|
+
raw_call(*args, method: :sh, **opts)
|
146
|
+
end
|
147
|
+
|
148
|
+
def call(*args, **opts)
|
149
|
+
tools=@config.local_devtools #this set up pacman and makepkg config files
|
150
|
+
env=opts.delete(:env) || {}
|
151
|
+
opts[:method]||=:run_simple
|
152
|
+
@dir.chdir do
|
153
|
+
tools.makepkg(*args, env: @env.merge(env), **opts)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def info(get: false)
|
158
|
+
if get
|
159
|
+
get_options={}
|
160
|
+
get_options=get if get.is_a?(Hash)
|
161
|
+
self.get(**get_options)
|
162
|
+
end
|
163
|
+
stdin=call("--printsrcinfo", chomp: :lines)
|
164
|
+
mode=nil; r={}; current={}; pkgname=nil
|
165
|
+
stdin.each do |l|
|
166
|
+
key, value=l.split(/\s*=\s*/,2)
|
167
|
+
next if key.nil?
|
168
|
+
if key=="pkgbase"
|
169
|
+
mode=:pkgbase
|
170
|
+
current[:pkgbase]=value
|
171
|
+
current[:repo]=@dir
|
172
|
+
elsif key=="pkgname"
|
173
|
+
if mode==:pkgbase
|
174
|
+
r=current
|
175
|
+
r[:pkgs]={}
|
176
|
+
else
|
177
|
+
r[:pkgs][pkgname]=current
|
178
|
+
end
|
179
|
+
current={}; mode=:pkgname; pkgname=value
|
180
|
+
else
|
181
|
+
key=key.strip.to_sym
|
182
|
+
Archlinux.add_to_hash(current, key, value)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
r[:pkgs][pkgname]=current #don't forget to update the last one
|
186
|
+
r
|
187
|
+
end
|
188
|
+
|
189
|
+
def packages(refresh=false, get: false)
|
190
|
+
@packages=nil if refresh
|
191
|
+
unless @packages
|
192
|
+
r=info(get: get)
|
193
|
+
pkgs=r.delete(:pkgs)
|
194
|
+
# r[:pkgbase]
|
195
|
+
base=Package.new(r)
|
196
|
+
list=pkgs.map do |name, pkg|
|
197
|
+
pkg[:name]=name
|
198
|
+
Package.new(pkg).merge(base)
|
199
|
+
end
|
200
|
+
@packages=@config.to_packages(list)
|
201
|
+
end
|
202
|
+
@packages
|
203
|
+
end
|
204
|
+
|
205
|
+
def get(logdir: nil, view: false, update: true, clone: true, pkgver: false)
|
206
|
+
if logdir
|
207
|
+
logdir=Pathname.new(logdir)
|
208
|
+
logdir.mkpath
|
209
|
+
end
|
210
|
+
get_pkg=self.get_pkg
|
211
|
+
|
212
|
+
if @dir.exist? and update
|
213
|
+
get_pkg.update(logdir: logdir)
|
214
|
+
elsif !@dir.exist? and clone
|
215
|
+
get_pkg.clone(logdir: logdir)
|
216
|
+
end
|
217
|
+
if view #view before calling pkgver
|
218
|
+
r=@config.view(@dir)
|
219
|
+
get_pkg.done_view if r and get_pkg.respond_to?(:done_view)
|
220
|
+
else
|
221
|
+
r=true
|
222
|
+
end
|
223
|
+
if r and pkgver and pkgver?
|
224
|
+
get_source
|
225
|
+
else
|
226
|
+
return r #abort pkgver
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# shortcut
|
231
|
+
def edit
|
232
|
+
get(view: true, update: false, clone: true, pkgver: false)
|
233
|
+
end
|
234
|
+
def edit_pkgbuild
|
235
|
+
get(view: false, update: false, clone: true, pkgver: false)
|
236
|
+
#TODO: @config.view_file/view_dir?
|
237
|
+
@config.view(@dir+"PKGBUILD")
|
238
|
+
end
|
239
|
+
|
240
|
+
def pkgver?
|
241
|
+
exist? and pkgbuild.read.match(/^\s*pkgver()/)
|
242
|
+
end
|
243
|
+
|
244
|
+
def get_source
|
245
|
+
success, _r=call('--nodeps', '--nobuild', method: :sh)
|
246
|
+
success
|
247
|
+
end
|
248
|
+
|
249
|
+
def make(*args, sign: config&.use_sign?(:package), default_opts: [], force: false, asdeps: @asdeps, **opts)
|
250
|
+
default_opts << "--sign" if sign
|
251
|
+
default_opts << "--key=#{sign}" if sign.is_a?(String)
|
252
|
+
default_opts << "--force" if force
|
253
|
+
default_opts << "--asdeps" if asdeps
|
254
|
+
default_opts+=@config[:makepkg][:build_args]
|
255
|
+
|
256
|
+
# error=13 means the package is already built, we consider that a success
|
257
|
+
success, _r=call(*args, method: :sh, default_opts: default_opts, env: @env, expected: 13, **opts)
|
258
|
+
get_pkg.done_build if success and get_pkg.respond_to?(:done_build)
|
259
|
+
success
|
260
|
+
end
|
261
|
+
|
262
|
+
def mkarchroot
|
263
|
+
args=@config.dig(:chroot, :packages) || ["base-devel"]
|
264
|
+
@config.chroot_devtools.mkarchroot(*args)
|
265
|
+
end
|
266
|
+
|
267
|
+
def makechroot(*args, sign: @config&.use_sign?(:package), force: false, **opts)
|
268
|
+
unless force
|
269
|
+
if list.all? {|f| f.exist?}
|
270
|
+
SH.logger.info "Skipping #{@dir} since it is already built (use force=true to override)"
|
271
|
+
return true #consider this a success build
|
272
|
+
end
|
273
|
+
end
|
274
|
+
devtools=@config.chroot_devtools
|
275
|
+
success=false
|
276
|
+
@dir.chdir do
|
277
|
+
success=devtools.makechrootpkg(*args, env: @env, **opts)
|
278
|
+
end
|
279
|
+
## signing should be done by 'build'
|
280
|
+
# self.sign(sign_name: sign) if sign and success
|
281
|
+
success
|
282
|
+
end
|
283
|
+
|
284
|
+
def build(*makepkg_args, mkarchroot: false, chroot: @config.dig(:chroot, :active), **opts)
|
285
|
+
force_sign = opts.delete(:rebuild) #when rebuilding we need to regenerate the signature
|
286
|
+
SH.logger.important "=> Building #{@dir}"
|
287
|
+
if chroot
|
288
|
+
self.mkarchroot if mkarchroot
|
289
|
+
success, _r=makechroot(*makepkg_args, **opts)
|
290
|
+
else
|
291
|
+
success, _r=make(*makepkg_args, **opts)
|
292
|
+
end
|
293
|
+
if success and (db=@config.db)
|
294
|
+
success=add_to_db(db, force_sign: force_sign)
|
295
|
+
if !chroot #sync db so that the new versions are available
|
296
|
+
tools=@config.local_devtools
|
297
|
+
tools.sync_db(db.repo_name)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
if success
|
301
|
+
packages.l.keys #return the list of built package
|
302
|
+
# TODO better handling of split dirs
|
303
|
+
else
|
304
|
+
success
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def install(*args, view: true, **opts)
|
309
|
+
r=get(view: view)
|
310
|
+
if r
|
311
|
+
build(*args, **opts)
|
312
|
+
else
|
313
|
+
r
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def list(**opts)
|
318
|
+
call("--packagelist", chomp: :lines, err: "/dev/null", **opts).map {|f| Pathname.new(f)}
|
319
|
+
end
|
320
|
+
|
321
|
+
def sign(sign_name: :package, **opts)
|
322
|
+
@config.sign(*list.select {|f| f.file?}, sign_name: sign_name, **opts)
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
class MakepkgList
|
328
|
+
extend CreateHelper
|
329
|
+
include MakepkgCommon
|
330
|
+
Archlinux.delegate_h(self, :@l)
|
331
|
+
attr_accessor :config, :cache, :l
|
332
|
+
|
333
|
+
def self.from_dir(dir=nil, config: Archlinux.config)
|
334
|
+
l=[]
|
335
|
+
dir=config.cachedir if dir.nil?
|
336
|
+
dir.children.each do |child|
|
337
|
+
if child.directory? and (child+"PKGBUILD").file?
|
338
|
+
l << child
|
339
|
+
end
|
340
|
+
end
|
341
|
+
self.new(l, config: config)
|
342
|
+
end
|
343
|
+
|
344
|
+
def initialize(l=[], config: Archlinux.config, cache: config.cachedir)
|
345
|
+
@config=config
|
346
|
+
@cache=Pathname.new(cache) if cache #how relative filenames are resolved; pass nil to use current dir
|
347
|
+
@l={}
|
348
|
+
merge(l)
|
349
|
+
end
|
350
|
+
|
351
|
+
def merge(l)
|
352
|
+
l.each do |m|
|
353
|
+
unless m.is_a?(Makepkg)
|
354
|
+
m=Pathname.new(m)
|
355
|
+
m = @cache+m if m.relative? and @cache
|
356
|
+
m=Makepkg.new(m, config: @config)
|
357
|
+
end
|
358
|
+
@l[m.name]=m
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def packages(refresh=false, get: false)
|
363
|
+
@packages = nil if refresh
|
364
|
+
if get
|
365
|
+
get_options={}
|
366
|
+
get_options=get if get.is_a?(Hash)
|
367
|
+
self.get(**get_options)
|
368
|
+
end
|
369
|
+
@packages ||= @l.values.reduce(@config.to_packages) do |list, makepkg|
|
370
|
+
list.merge(makepkg.packages(get: false))
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def get(*_args, view: true, pkgver: false, **opts)
|
375
|
+
Dir.mktmpdir("aur_view") do |d|
|
376
|
+
@l.values.each do |l|
|
377
|
+
l.get(*_args, logdir: d, view: false, pkgver: false, **opts) #l.get does not take arguments, we put them here for arg/opt ruby confusion
|
378
|
+
end
|
379
|
+
if view
|
380
|
+
r=@config.view(d)
|
381
|
+
if r
|
382
|
+
@l.values.each do |l|
|
383
|
+
l.get_pkg.done_view if l.get_pkg.respond_to?(:done_view)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
else
|
387
|
+
r=true
|
388
|
+
end
|
389
|
+
if r and pkgver
|
390
|
+
@l.values.map do |l| #all?
|
391
|
+
l.get_source if l.pkgver?
|
392
|
+
end
|
393
|
+
end
|
394
|
+
return r
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def make(*args)
|
399
|
+
@l.values.each do |l|
|
400
|
+
l.make(*args)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def makechroot(*args)
|
405
|
+
@l.values.each do |l|
|
406
|
+
l.makechroot(*args)
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
def mkarchroot
|
411
|
+
args=@config.dig(:chroot, :packages) || ["base-devel"]
|
412
|
+
@config.chroot_devtools.mkarchroot(*args)
|
413
|
+
end
|
414
|
+
|
415
|
+
def list
|
416
|
+
@l.values.flat_map { |l| l.list }
|
417
|
+
end
|
418
|
+
|
419
|
+
def build(*args, chroot: @config.dig(:chroot, :active), install: false, **opts)
|
420
|
+
mkarchroot if chroot
|
421
|
+
@config.pre_install(*args, makepkg_list: self, install: install, **opts)
|
422
|
+
built=@l.values.map do |l|
|
423
|
+
l.build(*args, chroot: chroot, **opts)
|
424
|
+
end
|
425
|
+
l_success=built.flat_map { |pkgs| pkgs || []}
|
426
|
+
@config.post_install(l_success, makepkg_list: self, install: install, **opts)
|
427
|
+
built
|
428
|
+
end
|
429
|
+
|
430
|
+
# Note that in build @config.{pre,post}_install is called
|
431
|
+
def pre_build(*args, **opts)
|
432
|
+
end
|
433
|
+
|
434
|
+
def post_build(*args, **opts)
|
435
|
+
end
|
436
|
+
|
437
|
+
|
438
|
+
def install(*args, view: true, **opts)
|
439
|
+
r=get(view: view)
|
440
|
+
pre_build(*args, **opts)
|
441
|
+
build(*args, **opts) if r
|
442
|
+
post_build(*args, **opts)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|