diff options
Diffstat (limited to 'bin/dtas-sourceedit')
-rwxr-xr-x | bin/dtas-sourceedit | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/bin/dtas-sourceedit b/bin/dtas-sourceedit index b411b11..1980141 100755 --- a/bin/dtas-sourceedit +++ b/bin/dtas-sourceedit @@ -1,16 +1,32 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors +# Copyright (C) 2013-2015, all contributors <dtas-all@nongnu.org> # 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} [-n|--dry-run][-V|--verbose] SOURCENAME\n" \ - "available SOURCENAME values: #{sources}" +usage = "Usage: #{DTAS_PROGNAME} [OPTIONS] SOURCENAME\n" \ + "available SOURCENAME values: #{sources}\n" \ -# use a real option parser if we have anything more complex -dry_run = !!(ARGV.delete('-n') || ARGV.delete('--dry-run')) -verbose = !!(ARGV.delete('-V') || ARGV.delete('--verbose')) +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" @@ -21,27 +37,51 @@ 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 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}" - system(cmd) or abort "#{cmd} failed: #$?" - buf = File.read(tmp.path) -end + cmd = "#{editor} #{tmp_path}" -source = YAML.load(buf) -cmd = %W(source ed #{name}) -update_cmd_env(cmd, orig, source) + sev = DTAS::Sigevent.new + rset = [ sev ] + if watch + ino = DTAS::Watchable::InotifyReadableIter.new + ino.watch_file(tmp_path, do_update) + rset << ino + end -# nil OK -%w(tryorder command).each do |field| - cmd << "#{field}=#{source[field]}" + trap(:CHLD) { sev.signal } + pid = Process.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 - -if verbose || dry_run - warn Shellwords.join(cmd) -end - -c.req_ok(cmd) unless dry_run |