From: Eric Wong <e@80x24.org>
To: dtas-all@nongnu.org
Subject: [PATCH 2/1] dtas-mlib: add dump support for debugging
Date: Sat, 28 Nov 2015 11:16:25 +0000 [thread overview]
Message-ID: <20151128111625.GA21697@dcvr.yhbt.net> (raw)
In-Reply-To: <20151127115054.16912-1-e@80x24.org>
Using an RFC-822-like format since YAML quoting rules aren't very
human-friendly, and we already prevent newlines from entering our
DB anyways.
---
bin/dtas-mlib | 18 +++++---
lib/dtas/mlib.rb | 134 +++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 132 insertions(+), 20 deletions(-)
diff --git a/bin/dtas-mlib b/bin/dtas-mlib
index 0e17d91..6331808 100755
--- a/bin/dtas-mlib
+++ b/bin/dtas-mlib
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# Copyright (C) 2015 all contributors <dtas-all@nongnu.org>
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
-usage = "#$0 [-d DATABASE-URI] ACTION [DIRECTORY]"
+usage = "#$0 [-d DATABASE-URI] ACTION [ARGS]"
Thread.abort_on_exception = $stderr.sync = $stdout.sync = true
require 'dtas/mlib'
require 'optparse'
@@ -27,13 +27,19 @@ unless db.include?('://')
end
end
+def mlib(db, migrate: false)
+ m = DTAS::Mlib.new(db)
+ m.migrate if migrate
+ m
+end
+
case action = ARGV.shift
-when 'update'
+when 'update', 'up'
directory = ARGV.shift or abort "DIRECTORY required\n#{usage}"
+ mlib(db, migrate: true).update(directory)
+when 'dump' # mainly for debugging
+ directory = ARGV.shift || '/'
+ mlib(db).dump(directory)
else
abort usage
end
-
-mlib = DTAS::Mlib.new(db)
-mlib.migrate
-mlib.__send__(action, directory)
diff --git a/lib/dtas/mlib.rb b/lib/dtas/mlib.rb
index 59a589c..9a112c9 100644
--- a/lib/dtas/mlib.rb
+++ b/lib/dtas/mlib.rb
@@ -11,6 +11,7 @@ class DTAS::Mlib
attr_accessor :follow_outside_symlinks
attr_accessor :follow_inside_symlinks
attr_accessor :tags
+
DM_DIR = -1
DM_IGN = -2
include DTAS::Process
@@ -240,6 +241,10 @@ class DTAS::Mlib
node[:id] = node_id
end
+ def node_lookup(parent_id, name)
+ @db[:nodes][name: name, parent_id: parent_id]
+ end
+
def node_ensure(parent_id, name, tlen, ctime = nil)
q = { name: name, parent_id: parent_id }
if node = @db[:nodes][q]
@@ -254,28 +259,33 @@ class DTAS::Mlib
node
end
- def scan_dir(path, st, parent_id = nil)
+ def cd(path)
prev_wd = @pwd
Dir.chdir(path)
cur = @pwd = Dir.pwd.b
-
- # TODO: use parent_id if given
- dir = dir_vivify(cur.split(%r{/+}n), st.ctime.to_i)
- Dir.foreach('.', encoding: Encoding::BINARY) do |x|
- case x
- when '.', '..', %r{\n}n
- # files with newlines in them are rare and last I checked (in 2008),
- # mpd could not support them, either. So lets not bother for now.
- next
- else
- scan_any(x, dir[:id])
- end
- end
+ yield
ensure
Dir.chdir(prev_wd) if cur && prev_wd
@pwd = prev_wd
end
+ def scan_dir(path, st, parent_id = nil)
+ cd(path) do
+ # TODO: use parent_id if given
+ dir = dir_vivify(@pwd.split(%r{/+}n), st.ctime.to_i)
+ Dir.foreach('.', encoding: Encoding::BINARY) do |x|
+ case x
+ when '.', '..', %r{\n}n
+ # files with newlines in them are rare and last I checked (in 2008),
+ # mpd could not support them, either. So lets not bother for now.
+ next
+ else
+ scan_any(x, dir[:id])
+ end
+ end
+ end
+ end
+
def send_harder(sock, msg)
sock.sendmsg(msg)
rescue Errno::EMSGSIZE
@@ -287,4 +297,100 @@ class DTAS::Mlib
warn "#{msg.bytesize} too big, dropped #{e.class}"
end
end
+
+ def find_dump_part(cur, base)
+ parts = @pwd.split(%r{/+}n)
+ parts.shift # no first part
+ parts << base if base
+ parts.each do |name|
+ if cur = node_lookup(cur[:id], name)
+ case cur[:tlen]
+ when DM_DIR then next # keep going
+ when DM_IGN then return [ :ignored, cur ]
+ else # regular audio
+ return cur if name.object_id == parts[-1].object_id
+ return [ :notdir, cur ]
+ end
+ else
+ return [ :missing, name ]
+ end
+ end
+ cur
+ end
+
+ # returns an array on error
+ def dump(path)
+ dir = path
+ base = nil
+ retried = false
+ begin
+ found = cd(dir) { find_dump_part(root_node, base) }
+ rescue Errno::ENOTDIR
+ raise if retried || found
+ dir, base = File.split(path)
+ retried = true
+ retry
+ end
+ return found if Array === found # error
+
+ # success
+ load_tags
+ require 'yaml'
+ @tag_rmap = @tag_map.invert
+ if found[:tlen] == DM_DIR
+ emit_recurse(found)
+ else
+ parent = @db[:nodes][id: found[:parent_id]]
+ parent or abort "missing parent for #{found.inspect}"
+ parent[:dirname] ||= path_of(parent)
+ emit_1(found, parent)
+ end
+ end
+
+ def path_of(node)
+ return '/' if node[:name] == ''
+ parts = [ node[:name], '' ]
+ begin
+ node = @db[:nodes][id: node[:parent_id]]
+ break if node[:id] == node[:parent_id]
+ parts.unshift node[:name]
+ end while true
+ parts.unshift('')
+ parts.join('/')
+ end
+
+ def emit_recurse(node)
+ node[:dirname] ||= path_of(node)
+ @db[:nodes].where(parent_id: node[:id]).order(:name).each do |nd|
+ next if nd[:id] == node[:id] # root_node
+ case nd[:tlen]
+ when DM_DIR then emit_recurse(nd)
+ when DM_IGN then next
+ else
+ emit_1(nd, node)
+ end
+ end
+ end
+
+ def emit_1(node, parent)
+ comments = Hash.new { |h,k| h[k] = [] }
+ @db['SELECT c.tag_id, v.val FROM comments c ' \
+ 'LEFT JOIN vals v ON v.id = c.val_id ' \
+ "WHERE c.node_id = #{node[:id]} ORDER BY c.tag_id"].map do |c|
+ comments[@tag_rmap[c[:tag_id]]] << c[:val]
+ end
+ puts "Path: #{parent[:dirname]}#{node[:name]}"
+ puts "Length: #{node[:tlen]}"
+ return if comments.empty?
+ puts 'Comments:'
+ comments.each do |k,v|
+ if v.size == 1
+ puts "\t#{k}: #{v[0]}"
+ else
+ v << ''
+ puts "\t#{k}:\n\t\t#{v.join("\t\t\n")}"
+ end
+ end
+ puts
+ end
end
--
EW
prev parent reply other threads:[~2015-11-28 11:16 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-27 11:50 [PATCH] introduce dtas-mlib for music library functions Eric Wong
2015-11-28 11:16 ` Eric Wong [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://80x24.org/dtas/README
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151128111625.GA21697@dcvr.yhbt.net \
--to=e@80x24.org \
--cc=dtas-all@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/dtas.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).