From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 208.118.235.0/24 X-Spam-Status: No, score=-2.4 required=3.0 tests=AWL,BAYES_00,URIBL_BLOCKED shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: dtas-all@80x24.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 3D31B200DB for ; Sun, 12 Apr 2015 09:57:02 +0000 (UTC) Received: from localhost ([::1]:44766 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YhEdQ-0007ty-Rv for dtas-all@80x24.org; Sun, 12 Apr 2015 05:57:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39787) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YhEdP-0007tp-Bs for dtas-all@nongnu.org; Sun, 12 Apr 2015 05:57:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YhEdM-0006bm-4h for dtas-all@nongnu.org; Sun, 12 Apr 2015 05:56:59 -0400 Received: from dcvr.yhbt.net ([64.71.152.64]:48598) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YhEdL-0006ba-Vm for dtas-all@nongnu.org; Sun, 12 Apr 2015 05:56:56 -0400 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id B8DCD1FDBA for ; Sun, 12 Apr 2015 09:56:53 +0000 (UTC) From: Eric Wong To: Subject: [PATCH] dtas-sinkedit: catch up to inotify/pipe changes in sourceedit Date: Sun, 12 Apr 2015 09:56:53 +0000 Message-Id: <1428832613-32124-1-git-send-email-e@80x24.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 64.71.152.64 X-BeenThere: dtas-all@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dtas-all-bounces+dtas-all=80x24.org@nongnu.org Sender: dtas-all-bounces+dtas-all=80x24.org@nongnu.org This is mainly for consistency in behavior with dtas-sourceedit. Using dtas-sourcedit is still more common and recommended as it is less likely to introduce audible gaps and pauses. --- bin/dtas-sinkedit | 100 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 20 deletions(-) diff --git a/bin/dtas-sinkedit b/bin/dtas-sinkedit index 3cf3a56..3a4bda8 100755 --- a/bin/dtas-sinkedit +++ b/bin/dtas-sinkedit @@ -1,42 +1,102 @@ #!/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 sinks = c.req('sink ls') || "(unknown)" -usage = "Usage: #{DTAS_PROGNAME} SINKNAME\n" \ +usage = "Usage: #{DTAS_PROGNAME} [OPTIONS] SINKNAME\n" \ "available SINKNAME values: #{sinks}" +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 sink') { + verbose = true + } + op.on('-h', '--help') { puts(op.to_s); exit } + op.parse!(ARGV) +end + ARGV.size == 1 or abort usage name = ARGV[0] -tmp = tmpyaml +st_in = $stdin.stat + buf = c.req(%W(sink cat #{name})) abort(buf) if buf =~ /\AERR/ orig = YAML.load(buf) -tmp.write(buf << DTAS_DISCLAIMER) -cmd = "#{editor} #{tmp.path}" -system(cmd) or abort "#{cmd} failed: #$?" -sink = YAML.load(File.read(tmp.path)) +commit_update = lambda do |buf| + sink = YAML.load(buf) + cmd = %W(sink ed #{name}) + update_cmd_env(cmd, orig, sink) -cmd = %W(sink ed #{name}) -update_cmd_env(cmd, orig, sink) + # both of these default to false + %w(nonblock active).each do |field| + cmd << "#{field}=#{sink[field] ? 'true' : 'false'}" + end -# both of these default to false -%w(nonblock active).each do |field| - cmd << "#{field}=#{sink[field] ? 'true' : 'false'}" -end + %w(prio).each do |field| + value = sink[field] and cmd << "#{field}=#{value}" + end -%w(prio).each do |field| - value = sink[field] and cmd << "#{field}=#{value}" -end + %w(pipe_size).each { |field| cmd << "#{field}=#{sink[field]}" } -%w(pipe_size).each { |field| cmd << "#{field}=#{sink[field]}" } + # nil OK + %w(command).each do |field| + cmd << "#{field}=#{sink[field]}" + end -# nil OK -%w(command).each do |field| - cmd << "#{field}=#{sink[field]}" + warn(Shellwords.join(cmd)) if verbose || dry_run + c.req_ok(cmd) unless dry_run + orig = sink end -c.req_ok(cmd) +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, Process::WNOHANG) + status or next + 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 -- EW