Sync Emacs Org Agenda Files via Dropbox Without Conflicts

null

I use beorg on iPad/iPhone to view my Emacs Org files. Until today, I did use it only for viewing files, not edit tasks, because I ran into sync conflicts.

This is how I solved the problem with a few simple1 settings.

Put org files into Dropbox

First, put your org files into the Dropbox. I have all .org files in one directory and use the directory as org-agenda-files:

(setq org-agenda-files (quote ("~/Pending/org/gtd")))

This will automatically expand directory contents using org-agenda-file-regexp, which by default is set to:

"\\`[^.].*\\.org\\'"

So it matches all non-hidden org files, nice.

Prevent sync conflicts

When you sync files, you externally change the files that correspond to buffers that are probably open at all times if you use Emacs org agenda. Once you edit files on your computer, either saving will not work because of conflicts, or you will be asked if you want to read buffer contents from disk again.

One part of avoiding conflicts is to save relevant org files often, the other part is auto-reloading from disk when possible.

Auto-save org buffers to disk

You can enable auto-saving of org files while emacs is running with a hook:

(add-hook 'auto-save-hook 'org-save-all-org-buffers)

That will put auto-saving all open org files on a timer. Performing changes to buffers from the org agenda overview, for example, doesn't mark the buffer as needing to auto-save, as far as I understand. So this setting helps to auto-save all org buffers regularly.

Auto-reload buffers when files on disk change

Then you can enable auto-reloading from disk when you change files in the Dropbox.

I am not comfortable having global-auto-revert-mode turned on, I'd rather limit this to my task lists. But if this is cool with you, just put (global-auto-revert-mode t) into your init.el file.

If you're like me and want to set only the task-related org buffers to auto-reload, you need to enable auto-revert-mode minor mode for these buffers. That will reload the buffer when the file changes like the global variant, but limited to a particular buffer.

Do not set this manually. There's a better way: auto-executing commands when files are loaded.

Emacs will execute whatever you put into a .dir-locals.el as soon as you open (aka "find") a file from that directory. This can be used to enable auto-revert-mode for all org files in your Dropbox.

In my case, the path would be ~/Pending/org/gtd/.dir-locals.el, and this is what I put inside:

; Enable auto-revert-mode for buffers from files from this directory:
((nil . ((eval . (auto-revert-mode 1)))))

Conclusion

Now when I open my org agenda, all org-agenda-files will be loaded to populate the agenda – that is all contents from this directory. Each and every corresponding buffer will have auto-reload-mode enabled, and thanks to the global settings, will save regularly to disk.

This isn't bullet-proof. I can still produce file conflicts easily when I change files on disk before the auto-save is triggered.

But you know what? I didn't even bother checking the auto-save interval settings. I want to save web links to my inbox.org and tick off items from my mobile devices, that's it. And when I'm on my mobile devices, minutes will have passed since I left my Mac and the files will already have synced. Same in the other direction. I don't sit in front of my Mac and tick off stuff on my iPad. That'd be stupid. So I don't produce sync errors under regular circumstances.

I'm happy with the result, and I hope your life will be better with this, too!


  1. Simple, of course, only in hindsight. As always, figuring out what I am really looking for when tweaking my Emacs setup is the worst part. For example, I was trying to write a ct/org-agenda-reload-all-buffers that calls revert-buffer for each agenda-managed buffer, and I was prepared to manually sync by hitting the "R" key from the agenda view like a caveman. Now I found a totally different approach. 

Browse the blog archive