My Personal AppleScript WTF



  • If I'm going to post this code, I must admit with shamed face that it was I who wrote it.


    if (get name extension of curDmg) is "dmg" then

    set oldDisk to get last disk

    open curDmg

    global mountedImage

    set mountedImage to get last disk

    --This loop waits until the disk image is actually mounted on the system.

    --We assume here that the newest disk mounted is the value of last disk.

    repeat until mountedImage is not oldDisk

    set mountedImage to get last disk

    end repeat


    In a nutshell, this code tells a disk image to mount, then waits for it to appear (which often takes considerable time). The WTF appears when we realize that in order to get reference to the mounted disk, I simply retrieve the last mounted volume repeatedly and check it to see if it has changed. If so, this is the reference I use for subsequent operations. Any guesses on what would happen if the user plugs in a USB drive after running the script, and the USB drive mounts first?


    The Real WTF, however, is that this seems to be the only way to do this; there does not appear to be any way to mount a disk image and get a reference back, or even to discover if a certain volume is associated with a certain disk image file. 



  • [quote user="ryos"]

    Any guesses on what would happen if the user plugs in a USB drive after running the script, and the USB drive mounts first?

    [/quote]

    I think it will result in the drive image being mounted on the USB drive. What might be interesting is the effect of removing the USB drive on the drive image reference.



  • Don't beat yourself up. It's been my experience that AppleScript is one giant WTF, so anything you write that will run is something to be proud of.



  • I thought, the real WTF was active waiting. Isn't it slowing down the whole process?



  • Here is a kludgy, but working, way to do exactly what you want to do. I am presuming Mac OS X, and tested this on 10.4.7. If you're using another version, YMMV.


    It's just two lines, although the first one is complicated; I'm assuming that the variable named "x" is the disk image as either an alias or a "file", not a string.

    set y to do shell script "perl -e '$a = quotemeta(shift()); $b = qx/hdiutil mount $a/; $b =~ m-(/Volumes/.*)$-; print $1;' " & the quoted form of (the POSIX path of x)
    (y as POSIX file) as alias

    Here's the logic, in case you're nervous:

    There is no way to use AppleScript to tell if a given disk is a mounted disk image. (Especially with Finder AppleScript as broken as it currently is!) So there's no point in mounting the disk and then checking to see what type all the disks are.

    The easiest way to mount a disk image, programmatically, is to use the command line, which means the horribly complex command "hdiutil". (The sendmail of disk commands, combined with a really stupid syntax. But it works really well, which is the important part.)

    The output of hdiutil's "attach" (or "mount", they are both understood) is a list of partitions from the image, and in this list, each mounted partition tells where it was mounted at the end of the line. A standard disk image will only have one mountable partition, and by default, things are mounted into /Volumes. So we need to look for a line in the output which ends in /Volumes/[Disk Name]. You could use grep on the output, or execute the whole thing inside Perl, or probably use some other option. I chose Perl because I'm used to it.

    Now, we'll be passing Perl a one-line script, and the path to the image, which means if we were just using the command line, it would look like this: "perl -e '[Script Goes Here]' [Escaped Path To Image]". The first part is easy, just avoid all quoting characters (which Perl makes easy by supporting generalized quoting). You just have to remember to escape the path before passing it back out from Perl, in case there are spaces or other characters the command-line doesn't like. The escaped path you get out of AppleScript using "the quoted form of (the POSIX path of [alias or file])".

    Finally: the output of the script is something like
    /Volumes/DiskName
    which is just a POSIX path to the disk. AppleScript can convert that from a POSIX path back to an alias, which is the second line. (You could even wrap the first line up and avoid the second line, but that would make things even more complicated-looking. Why bother?)



  • [quote user="qbolec"]I thought, the real WTF was active waiting. Isn't it slowing down the whole process?[/quote]


    Actually, it doesn't use much CPU at all. Even with a disk image mounting at the same time, the CPU is far from pegged. And I'm on a 1ghz PowerBook G4.

    Thanks for the suggestion, Vicar! I'll definitely look into that, when I have time. :) 



  • [quote user="ryos"]Thanks for the suggestion, Vicar! I'll definitely look into that, when I have time. :) 
    [/quote]


    No problem. I used to do a lot of stuff with AppleScript, even wrote some Scripting Additions years ago. Forgotten a lot of it now, although I still remember the First Rule Of Avoiding AppleScript Frustration. (Use at least twice as many parentheses as Script Editor inserts automatically.)

    Speaking of time, though: if your disk images are taking more than 2 minutes to verify before mounting (this may be the case if they're big or stored on a slow disk), don't forget to wrap the mounting process in a "with timeout of [large number here] seconds" block, or you'll end up beating your head against the wall at some point.



  • [quote user="codewallah"]Don't beat yourself up. It's been my experience that AppleScript is one giant WTF
    [/quote]


    What else would you expect from an extensible language with a syntax and vocabulary that's supposed to resemble natural English?


Log in to reply