···1414# Redistribution and use in source and binary forms, with or without
1515# modification, are permitted provided that the following conditions
1616# are met:
1717-#
1717+#
1818# 1. Redistributions of source code must retain the above copyright
1919# notice, this list of conditions and the following disclaimer.
2020# 2. Redistributions in binary form must reproduce the above copyright
···2222# documentation and/or other materials provided with the distribution.
2323# 3. The name of the author may not be used to endorse or promote products
2424# derived from this software without specific prior written permission.
2525-#
2525+#
2626# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
2727# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2828# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
···5555 end
5656else
5757 puts "error: directory \"#{destdir}\" does not exist, exiting"
5858- exit
5858+ exit 1
5959end
60606161-print "querying itunes for playlist \"#{playlist}\"... "
6161+puts "querying itunes for playlist \"#{playlist}\"..."
62626363itunes = Appscript.app.by_name("iTunes", ITunesFix)
6464+begin
6565+ if !(itpl = itunes.playlists[playlist])
6666+ raise "no such playlist with that name"
6767+ end
64686565-itpl = itunes.playlists[playlist]
6969+ tracks = itpl.file_tracks.get.map{|t| t.location.get.path }
7070+rescue => e
7171+ puts "could not find playlist #{playlist.inspect}, exiting"
7272+ exit 1
7373+end
66746767-if !itpl
6868- puts "could not locate, exiting"
6969- exit
7070-end
7575+# figure out how much space we're going to take
7676+bytes = 0
7777+tracks.each{|t| bytes += File.size(t) }
7878+mbytes = bytes.to_f / (1024 * 1024)
71797272-tracks = itpl.file_tracks.get.map{|t| t.location.get.path }
8080+puts "found #{tracks.length} track#{tracks.length == 1 ? "" : "s"} with " +
8181+ "size #{sprintf("%0.2fMb", mbytes)}"
73827474-puts "found #{tracks.length} track#{tracks.length == 1 ? '' : 's'}."
8383+# make sure the destination can take it
8484+df_m = `df -m #{destdir}`.split("\n").last.split(" ")[1].to_i
8585+if mbytes > df_m
8686+ puts "error: #{destdir} has size of #{df_m}Mb, need #{mbytes.ceil}Mb to sync"
8787+ exit 1
8888+end
75897676-# figure out where all of them are stored by checking for the greatest common
9090+# figure out where all tracks are stored by checking for the greatest common
7791# directory of every track
7892gcd = ""
7993(1 .. tracks.map{|t| t.length }.max).each do |s|
···93107 end
94108end
951099696-# setup work dir
97110td = `mktemp -d /tmp/itunes-rsync.XXXXX`.strip
981119999-# mirror directory structure and create symlinks
112112+# link each track into the workspace
100113print "linking files under #{td}/... "
101101-102114tracks.each do |t|
103115 shortpath = t[gcd.length .. t.length - 1]
104116 tmppath = "#{td}/#{shortpath}"
105117118118+ # restrict pathnames to avoid indexing problems on some players/filesystems
119119+ tmppath.gsub!(/[^A-Za-z0-9\.\/,' -]/, "_")
120120+106121 if !Dir[File.dirname(tmppath)].any?
107107- # i'm too lazy to emulate -p with Dir.mkdir
108122 system("mkdir", "-p", File.dirname(tmppath))
109123 end
110124···115129116130# times don't ever seem to match up, so only check size
117131puts "rsyncing to #{destdir}... "
118118-system("rsync", "-Lrv", "--size-only", "--delete", "#{td}/", destdir)
132132+system("rsync", "-Lrv", "--size-only", "--progress", "--delete",
133133+ "#{td}/", destdir)
119134120135print "cleaning up... "
121136system("rm", "-rf", td)