3

My problem is that I can create, but not overwrite existing files. This is probably due to a bug in MegaFuse. Because of this, when I finish editing a file I must first save it under a different name, and then replace the original by hand. Of course, this also affects emacs' auto-save and backup, because it only functions well on the first attempt.

I'd be happy enough with a function/command that could simply do:

delete-file <current-buffer-name>
write-file <current-buffer-name>

(I'm still an early beginner on emacs matters, and I still don't understand lisp very well.)

Btw, do you know any keybinding I could use for this command?

2

The functions you want are delete-file:

(delete-file FILENAME &optional TRASH)

Delete file named FILENAME. If it is a symlink, remove the symlink. If file has multiple names, it continues to exist with the other names. TRASH non-nil means to trash the file instead of deleting, provided ‘delete-by-moving-to-trash’ is non-nil.

When called interactively, TRASH is t if no prefix argument is given. With a prefix argument, TRASH is nil.

and buffer-file-name:

(buffer-file-name &optional BUFFER)

Return name of file BUFFER is visiting, or nil if none. No argument or nil as argument means use the current buffer.

We can can combine them into a function, making sure that buffer-file-name is non-nil before we try to delete it. This function could also run save-buffer, but it sounds like what you really want is to always delete the file just before saving it, which is what before-save-hook is for

(defun delete-if-file ()
  (if (buffer-file-name)
      (delete-file (buffer-file-name))
    ))

(add-hook 'before-save-hook #'delete-if-file)

I haven't really tested this except to check that files are getting saved. Since it deletes things, you should be careful.

  • Thank you for your help! Just a note though, I think (true-filename buffer-file-name) would be more appropriate than simply (buffer-file-name) because it avoids destroying symlinks. – g4v3 Jun 8 '15 at 8:12
  • Good point. I hadn't thought about symlinks. – erikstokes Jun 8 '15 at 12:31
1

Emacs works like this by default: when it saves a file, it moves the existing file to the backup file (rename("foo", "foo~")), which unlinks the backup file, and it creates a new file to write to. This is controlled by the backup-by-copying variable; the default value is nil, meaning the rename-and-new strategy.

There are a number of circumstances when Emacs will instead copy the existing file to the backup file (open("foo~", O_TRUNC)) then save the buffer to the existing file (open("foo", O_TRUNC)), basically when Emacs thinks it won't be able to create a file with the same permissions or hard links.

Auto-save files are in your home directory by default, so they aren't a problem.

Seeing the bug, I suspect that your problem is not in fact that you cannot write the file, but rather that the filesystem advertises the file as read-only. If that's the case, then Emacs would believe that it can't re-create the file (which is a bit weird: Emacs applies the copy-and-overwrite strategy if it doesn't have the permission to overwrite the file!), which is one of the conditions that make it apply the copy-and-overwrite strategy.

Here's some heavy-handed code that forces Emacs to use the rename strategy in that case. Untested.

(defadvice backup-buffer
  (around backup-buffer-by-renaming-on-megafuse activate)
  (if (save-match-data
        (string-match megafuse-directory-regexp (file-chase-links buffer-file-name)))
      (letf (((symbol-function 'backup-buffer-copy)
              (lambda (from-name to-name modes extended-attributes)
                (rename-file from-name to-name t))))
        ad-do-it)
    ad-do-it))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.