From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zachary Newman Subject: org-attach and UUID case Date: Tue, 09 Jul 2019 13:46:43 -0400 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:470:142:3::10]:40662) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hkuCy-0006aC-QR for emacs-orgmode@gnu.org; Tue, 09 Jul 2019 13:47:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hkuCv-0007gH-3V for emacs-orgmode@gnu.org; Tue, 09 Jul 2019 13:47:15 -0400 Received: from wnew4-smtp.messagingengine.com ([64.147.123.18]:51597) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hkuCs-0007OT-6J for emacs-orgmode@gnu.org; Tue, 09 Jul 2019 13:47:10 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.west.internal (Postfix) with ESMTP id 0EE8738E for ; Tue, 9 Jul 2019 13:46:44 -0400 (EDT) Received: from 30-10-22.wireless.csail.mit.edu.znewman.net (30-10-22.wireless.csail.mit.edu [128.30.10.22]) by mail.messagingengine.com (Postfix) with ESMTPA id 94D4D380074 for ; Tue, 9 Jul 2019 13:46:43 -0400 (EDT) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: emacs-orgmode@gnu.org *tl;dr*: ~org-id-new~ sometimes generates upcase UUIDs, sometimes downcase. Combined with case-insensitive filesystems, this can be bad. I have a workaround, wondering if a fix is appropriate. It appears that on my MacBook, ~org-id-new~ uses upper-case while on my Nix= OS box it uses lowercase (I believe because ~uuidgen~ is not available). This *should* be fine, but I sync my org files via Dropbox, which will do things *like: if there's a file ~FOO~ and you add a file ~foo~, it'll (very *helpfully) rename ~foo~ to ~FOO (Case Conflict)~. See https://help.dropbox.com/installs-integrations/sync-uploads/case-confli= ct This means if we: 1. create an attachment with UUID beginning with e.g. ~ff~ 2. create another attachment with UUID beginning with ~FF~ (pretty likely d= ue to birthday paradox) 3. wait for Dropbox to rename the latter 4. try to do anything with the latter attachment org cannot find the attachment directory! I'd consider this mostly the fault of Dropbox, but in general I'd hope that org would play nice when syncing across filesystems. We can fix it pretty simply (thanks, Gustav Wikstr=C3=B6m, for commit ae9cd= 437!): #+BEGIN_SRC emacs-lisp (setq org-attach-id-to-path-function (lambda (id) (upcase (org-attach-id-folder-format id)))) #+END_SRC However, if we have some pre-existing directories, we run into trouble (the= y can no longer be found!). I patched mine up by hand (because I was doing this f= rom a case-insensitive filesystem, which made the whole thing a nightmare). See post-script for an automated way to do it. Is it worth trying to prevent this? We could: - make generated UUIDs consistent case (upcase/downcase the output of ~org-id-uuid-program~) - make ~org-attach-id-to-path-function~ upcase/downcase by default I'd lean towards the latter option. If we do that, we'd have to handle existing "wrong"-cased attachment directories for users, but we have a few options for doing so: - check all cases on disk when computing ~(org-attach-dir)~ and silently us= e the right one - check all cases and set ~:DIR:~ (with prompt?) for the entry - check all cases and move the dir to the right case (with prompt) - provide a one-time migration function I'd lean towards the second option, with a prompt. I'm happy to work on it (and sign over the copyright etc.), but would like = to make sure that it's something we actually want to do and the approach is acceptable before beginning. Or it might be too much of an edge-case to cha= nge things for. Cheers, Zack P.S. Something like the following should work if your filesystem is case-se= nsitive (not totally tested): #+BEGIN_SRC emacs-lisp (defun get-path-variants (path) (let* ((path-parts (split-string path "/")) (basedir (mapconcat 'identity (butlast path-parts 2) "/")) (part1 (car (last path-parts 2))) (part2 (cadr (last path-parts 2)))) (list (concat basedir "/" (downcase part1) "/" (downcase part2)) (concat basedir "/" (downcase part1) "/" (upcase part2)) (concat basedir "/" (upcase part1) "/" (downcase part2)) (concat basedir "/" (upcase part1) "/" (upcase part2))))) (defun normalize-attach-dir () (let* ((attach-dir (org-attach-dir))) (mapc (lambda (attach-dir-variant) (if (and (file-exists-p attach-dir-variant) (not (string=3D attach-dir-variant attach-dir))) (rename-file attach-dir-variant attach-dir))) (get-path-variants -attach-dir)) (org-set-property "ID" (upcase (org-entry-get (point) "ID" nil))))) (defun attach-dir-matcher (todo tags-list level) (not (eq (org-attach-dir) nil))) (defun normalize-attach-dirs () (mapc (lambda (file) (with-current-buffer (org-get-agenda-file-buffer file) (org-scan-tags #'normalize-attach-dir #'attach-dir-matcher nil)= )) (org-agenda-files t))) #+END_SRC