#!/usr/bin/env ruby # Copyright (C) 2013-2015, all contributors # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) require 'optparse' require 'dtas/edit_client' require 'dtas/sigevent' require 'dtas/watchable' include DTAS::EditClient c = client_socket sources = c.req('source ls') || "(unknown)" usage = "Usage: #{DTAS_PROGNAME} [OPTIONS] SOURCENAME\n" \ "available SOURCENAME values: #{sources}\n" \ dry_run = verbose = false watch = defined?(DTAS::Watchable) OptionParser.new('', 24, ' ') do |op| op.banner = usage watch and op.on('-N', '--no-watch', 'disable inotify support') { watch = false } op.on('-n', '--dry-run', 'only print commands, do not run them') { dry_run = true } op.on('-V', '--verbose', 'print out commands sent to change the source') { verbose = true } op.on('-h', '--help') { puts(op.to_s); exit } op.parse!(ARGV) end ARGV.size <= 1 or abort usage name = ARGV[0] || "sox" st_in = $stdin.stat buf = c.req(%W(source cat #{name})) abort(buf) if buf =~ /\AERR/ orig = YAML.load(buf) commit_update = lambda do |buf| source = YAML.load(buf) cmd = %W(source ed #{name}) update_cmd_env(cmd, orig, source) # nil OK %w(tryorder command).each { |field| cmd << "#{field}=#{source[field]}" } warn(Shellwords.join(cmd)) if verbose || dry_run c.req_ok(cmd) unless dry_run orig = source end if st_in.file? || st_in.pipe? buf = $stdin.read commit_update.call(buf) else include DTAS::SpawnFix tmp = tmpyaml tmp_path = tmp.path do_update = lambda { commit_update.call(File.read(tmp_path)) } tmp.write(buf << DTAS_DISCLAIMER) cmd = "#{editor} #{tmp_path}" sev = DTAS::Sigevent.new rset = [ sev ] if watch ino = DTAS::Watchable::InotifyReadableIter.new ino.watch_file(tmp_path, do_update) rset << ino end trap(:CHLD) { sev.signal } pid = spawn(cmd) begin r = IO.select(rset) or next r[0].each do |io| case io when sev _, status = Process.waitpid2(pid) status.success? or abort "#{cmd} failed: #{status.inspect}" do_update.call exit when ino ino.readable_iter # calls do_update end end end while true end