Skip to content
Snippets Groups Projects
Verified Commit 580edd48 authored by Jan Alexander Steffens (heftig)'s avatar Jan Alexander Steffens (heftig)
Browse files

archbuild: Add gitpkg helper

parent 517eed4f
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/ruby
require 'optparse'
require 'readline'
$options = {}
OptionParser.new do |opts|
opts.banner = <<~END
Usage: #{File.basename($0)} [Git URI]
Maintains Git-source PKGBUILDs. Allows selecting a new commit to build.
If first source is not a git URI, tries to alter PKGBUILD to port from
autotools distributed source to a git repo. If an absolute Git URI is
not provided, derives a GNOME Git URI automatically.
Otherwise, if a Git URI is provided, replaces the first source with the
provided URI.
Submodules aren't yet handled. Remember to properly source and inject
any submodules required.
Options:
END
opts.on("-h", "--help", "Print this help") do
puts opts
exit
end
end.parse!
def header(s)
puts "\n\e[1m#{s}:\e[0m"
end
class Pkgbuild
attr_reader :filename, :contents
def initialize(filename="PKGBUILD")
@filename = filename
@contents = File.read filename
end
def =~(regex)
@contents =~ regex
end
def has_var?(name)
@contents =~ /^#{name}=/
end
def has_func?(name)
@contents =~ /^#{name}\(\)/
end
end
class PkgbuildWriter < Pkgbuild
def write
File.write(@filename, @contents)
end
def sub(*args, &block)
@contents.sub!(*args, &block)
end
def gsub(*args, &block)
@contents.gsub!(*args, &block)
end
def insert_func(content, where=/[A-Za-z0-9_-]+/)
@contents.sub!(/^#{where}\(\)/, "#{content}\n\\&")
end
def replace_var(name, content=nil, after: nil, before: nil)
content.nil? ^ !block_given? or raise ArgumentError, "need either content or block"
after.nil? ^ before.nil? or raise ArgumentError, "need either after: or before:"
var_re = lambda { |var| /^#{var}=(\([^)]*\)|.*$)/ }
if has_var? name
@contents.sub!(var_re[name]) { "#{name}=#{content || yield($1)}" }
return false
end
repl = "#{name}=#{content || yield("")}"
if !after.nil?
@contents.sub!(var_re[after]) { $& + "\n" + repl }
else
@contents.sub!(var_re[before]) { repl + "\n" + $& }
end
true
end
def append_array(name, content, **kwargs)
replace_var(name, **kwargs) do |orig|
if orig =~ /^\(([^)]+)\)$/
"(#{$1} #{content})"
else
"(#{content})"
end
end
end
end
class PkgbuildReader < Pkgbuild
attr_reader :pkgbase, :basevar, :makedepends, :source
def initialize(*args)
super
@bash = IO.popen ["bash"], "w+"
@bash.puts "{", @contents, "} &>/dev/null"
@pkgbase = read :pkgbase
@basevar = :pkgbase
if @pkgbase.empty?
@pkgbase = read :pkgname
@basevar = :pkgname
end
@makedepends = readarray :makedepends
@source = readarray :source
end
def exec(*lines)
lines.each { |l| @bash.puts l }
@bash.puts "printf '\\x00ENDEXEC\\x00'"
buf = ""
buf << @bash.readchar until buf[-1] == ?\x00 && buf =~ /\x00ENDEXEC\x00\Z/
buf[0..-10]
end
def read(varname)
exec("printf '%s' \"${#{varname}}\"")
end
def readarray(varname)
exec("printf '%s\\x00' \"${#{varname}[@]}\"").split("\x00")
end
end
class Repo
SRCDEST = "/var/lib/archbuilddest/srcdest"
DISCOVER_URLS = [
"https://anongit.freedesktop.org/git/",
"https://git.gnome.org/browse/",
"https://github.com/",
]
attr_reader :name, :url
def self.is_git_src?(src)
src =~ /(^|::)git(\+https?)?:\/\//
end
def self.split_src(src)
name, url = src =~ /::/ ? src.split("::", 2) : [nil, src.dup]
url.sub!(/#.*/, "")
url.sub!(/^git\+/, "")
[name, url]
end
def self.exists?(src)
_name, url = split_src src
!!Kernel.system('git', 'ls-remote', url, out: "/dev/null", err: [:child, :out])
end
def self.discover(src)
name, url = split_src src
if url !~ /:\/\//
url = DISCOVER_URLS.map { |u| u + url }.find do |u|
puts "Trying #{u}"
exists?(u)
end
raise "Discover failure" if url.nil?
end
url.prepend "git+" unless Repo.is_git_src?(name)
url << "#commit=$_commit"
return "#{name}::#{url}" unless name.nil?
return url
end
def initialize(src)
@name, @url = self.class.split_src(src)
@name = url.sub(/(\.git)?\/?$/, "").sub(/^.*\//, "") if @name.nil?
@dir = File.join(SRCDEST, name)
if test ?e, @dir
system('git', 'fetch', '--all', '-p')
else
Dir.chdir(SRCDEST) do
Kernel.system('git', 'clone', '--mirror', url, name) or raise "Clone failure"
end
end
@refs = read('git', 'for-each-ref', '--sort=v:refname', '--format=%(refname)',
'refs/heads/*', 'refs/tags/*').lines.
map { |l| l.strip.sub(/^refs\/(heads|tags)\//, "") }
end
def system(*args)
Dir.chdir(@dir) do
Kernel.system(*args)
end
end
def read(*args)
ret = IO.popen(args, chdir: @dir) { |f| f.read }
if !$?.exited?
raise "#{args[0] == "git" ? args[1] : args[0]} failed"
elsif !$?.exitstatus.zero?
raise "#{args[0] == "git" ? args[1] : args[0]} failed, exit #{$?.exitstatus}"
end
ret
end
def resolve(ref)
read('git', 'rev-parse', '--verify', '-q', "#{ref}^{commit}").chomp
end
def describe(*args)
read('git', 'describe', '--tags', *args).chomp
end
def read_file(ref, file)
read 'git', 'show', "#{ref}:#{file}"
end
def log(*args)
system('git', 'log', '--first-parent', '-m', '--decorate', *args)
end
def complete_ref(s)
@refs.grep(/^#{Regexp.escape s}/)
end
def choose_commit
header "Branches"
system 'git', 'branch'
header "Tags"
system 'git', 'tag'
begin
old_char = Readline.completion_append_character
old_proc = Readline.completion_proc
Readline.completion_append_character = ""
Readline.completion_proc = method(:complete_ref).to_proc
commit = nil
loop do
puts
if (ref = Readline.readline("Enter ref (or nothing to view all): ", true).strip).empty?
system('tig', '--all', '--date-order') or log('--graph', '--all', '--oneline')
else
begin
commit = resolve ref
break
rescue => e
puts "Failed to resolve ref (#{e})"
end
end
end
ensure
Readline.completion_append_character = old_char
Readline.completion_proc = old_proc
end
log '--stat=80', commit
system 'git', 'show', "#{commit}:NEWS"
commit
end
end
pbr = PkgbuildReader.new
reposrc = pbr.source.first
gitify = !Repo.is_git_src?(reposrc)
case ARGV.count
when 0
reposrc = Repo.discover(pbr.pkgbase) if gitify
when 1
reposrc = Repo.discover(ARGV.first)
else
raise "Invalid number of arguments"
end
repo = Repo.new reposrc
commit = repo.choose_commit
commit_comment = repo.describe('--contains', '--all', commit)
pbw = PkgbuildWriter.new
pbw.replace_var :_commit, "#{commit} # #{commit_comment}", before: :source
pbw.sub(/source=\([^) \n]+/, "source=(\"#{reposrc}\"") unless pbr.source.first == reposrc
if gitify
autogen = repo.read_file(commit, "autogen.sh") rescue ""
configure = repo.read_file(commit, "configure.ac") rescue ""
add_md = lambda do |name, cond=true|
if !pbr.makedepends.grep(name).empty?
true
elsif cond
pbw.append_array(:makedepends, name, after: :depends)
true
else
false
end
end
unless add_md["gnome-common",
(autogen =~ /gnome-autogen\.sh/ || configure =~ /^GNOME_[A-Z_]+(\(|$)/)]
add_md["gtk-doc", configure =~ /^GTK_DOC_CHECK/]
add_md["yelp-tools", configure =~ /^YELP_HELP_INIT/]
add_md["autoconf-archive", configure =~ /^AX_/]
add_md["intltool", configure =~ /^IT_PROG_INTLTOOL/]
end
add_md["appstream-glib", configure =~ /^APPSTREAM_/]
add_md["vala", configure =~ /^AM_PROG_VALAC/]
add_md["git"]
if pbr.pkgbase == repo.name
localname = "$#{pbr.basevar}"
else
localname = repo.name
end
pbw.gsub(/(\${?#{pbr.basevar}}?|#{repo.name})-\${?pkgver}?/, localname)
if pbr !~ /autogen\.sh/
pbw.insert_func <<~END
prepare() {
cd #{localname}
NOCONFIGURE=1 ./autogen.sh
}
END
end
sed = ""
begin
describe = repo.describe(commit)
sed << "s/^#{$&}//;" if describe =~ /^\D+/
sed << "s/_/./g;" if describe =~ /_/
rescue => e
warn "pkgver() deduction failed: #{e}"
end
sed << "s/-/+/g"
pbw.insert_func <<~END
pkgver() {
cd #{localname}
git describe --tags | sed '#{sed}'
}
END
end
pbw.write
system "updpkgsums"
system "makepkg", "--verifysource"
header "Diff"
IO.popen(['diff', '-u', '-', pbw.filename], "w") { |f| f.write pbr.contents }
header "Submodules"
gitmodules = repo.read_file(commit, ".gitmodules") rescue ""
if gitmodules =~ /submodule/
puts gitmodules
else
puts "None"
end
Dir.unlink "src"
File.unlink(*Dir.glob("*.pkg.tar.xz"))
......@@ -10,6 +10,7 @@
- diffrepo
- clean-chroots
- clean-dests
- gitpkg
- name: install archbuild units
copy: src={{ item }} dest=/etc/systemd/system/{{ item }} owner=root group=root mode=0644
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment