girzel / ebdb

An EIEIO port of BBDB, Emacs' contact-management package
67 stars 11 forks source link

Searching database causes error #48

Closed swflint closed 7 years ago

swflint commented 7 years ago

Currently attempting to search database (have latest revision), and am consistently getting the following error: No applicable method: ebdb-string, nil.

girzel commented 7 years ago

Thanks for the report. Are you loading from a github clone, or from Elpa? Can you tell me which extra packages (MUAs, ebdb-i18n, etc) you have loaded? Does it error every time? How many record do you have?

swflint commented 7 years ago

Github clone. Loading ebdb-gnus, ebdb-message, ebdb-org and ebdb-pgp. 184 records including some organizations (131 people, 53 organizations). Every time I try to query it, and it won't complete email addresses either.

Config is as follows:

(add-directory-to-load-path "ebdb")
(require 'ebdb)
(require 'ebdb-gnus)
(require 'ebdb-message)
(require 'ebdb-org)
(require 'ebdb-pgp)
(setf ebdb-sources "~/.emacs.d/ebdb-data"
      ebdb-complete-mail-allow-cycling t
      ebdb-read-name-articulate t
      ebdb-default-country "USA")
(ebdb-load)
girzel commented 7 years ago

Does it load and initialize correctly, then only barf on search? Or does it barf on load?

Due to some very annoying aspects of how objects are currently handled in Emacs, toggling debug on error results in the object being printed as part of the backtrace, which dumps a horrible amount of text into Message. If I can't get any other clues, however, I might have to ask you to do that...

girzel commented 7 years ago

Sorry, one more thing: would you try searching on different fields, and tell me which errors? I suspect it's the name field, would you try explicitly searching on the name field "/ n", then also try some other fields, and tell me which error and which don't? Thanks.

swflint commented 7 years ago

So it does barf only on search. It seems to be when it tries to format stuff, so I'm unable to even get to a point of being able to search different fields. Even M-x ebdb RET RET errors out, so I'm unable to maniupulate it in any way.

swflint commented 7 years ago

For reference, ebdb-display-all-records has the same error.

girzel commented 7 years ago

Okay, so it's display, not searching.

I've looked through the code, and the only place I can see where this could happen is in the display of role fields, when the corresponding person or organization hasn't been hashed. That shouldn't happen unless roles are created across multiple databases and then one of the databases isn't loaded, but... bugs shouldn't happen.

Assuming that's it, would you please do the following:

  1. Kill all *EBDB* buffers and run M-: (ebdb-clear-vars)
  2. Run M-: (require 'ebdb-com)
  3. eval-region on all the code below
  4. Run M-x ebdb-display-all-records
  5. Hopefully that will both allow the display of the *EBDB* buffer, and some debugging output in *Message*, please send me whatever you get.
(cl-defmethod ebdb-fmt-field ((fmt ebdb-formatter-ebdb)
                  (field ebdb-field-role)
                  _style
                  (record ebdb-record-organization))
  (let* ((person (ebdb-gethash (slot-value field 'record-uuid) 'uuid))
     (mail (slot-value field 'mail))
     (value (if person
            (ebdb-string person)
          (format "unloaded person %s" (slot-value field 'record-uuid)))))
    (unless person
      (message "Failed to load person for %s role on org %s"
           (eieio-object-name-string field) (ebdb-string record)))
    (if (slot-value field 'defunct)
    (propertize value 'face 'ebdb-defunct)
      value)))

(cl-defmethod ebdb-fmt-field ((fmt ebdb-formatter-ebdb)
                  (field ebdb-field-role)
                  _style
                  (record ebdb-record-person))
  (let* ((org (ebdb-gethash (slot-value field 'org-uuid) 'uuid))
     (mail (slot-value field 'mail))
     (value (if org
            (ebdb-string org)
          (format "unloaded org %s" (slot-value field 'org-uuid)))))
    (unless org
      (message "Failed to load org for %s role on person %s"
           (eieio-object-name-string field) (ebdb-string record)))    
    (if (slot-value field 'defunct)
    (propertize value 'face 'ebdb-defunct)
      value)))
swflint commented 7 years ago

That worked!

#s(hash-table size 730 test equal weakness value rehash-size 1.5 rehash-threshold 0.8 data ( ...))
ebdb-com
Mark set
Quit
Loading EBDB sources...
Initializing EBDB records... done
Formatting EBDB...done.
swflint commented 7 years ago

And as it stood, it wasn't completing stuff either.

swflint commented 7 years ago

And it still isn't completing addresses in message-mode buffers.

girzel commented 7 years ago

Hang on, one thing at a time! Can you tell me if there was anything in *Messages *? There's still some underlying bug going on, and the failure of message-mode completion is likely due to the same problem.

You don't have multiple databases, do you?

swflint commented 7 years ago

No messages when I hit tab or do M-x ebdb-complete-mail.

I have one database (see config in initial report).

girzel commented 7 years ago

I meant, was there anything in *Messages* after display? If the code above solved the display problem, there should have been something in *Messages*.

swflint commented 7 years ago

Formatting ebdb...done.

girzel commented 7 years ago

And after you display all the records, does the string "Failed to load" appear anywhere in the *EBDB* buffer?

swflint commented 7 years ago

No Failed to load but I do see some unloaded person uuid and unloaded org uuid.

girzel commented 7 years ago

Okay, between this and the problem with completion, it's clear that something is going wrong in the initialization process, and the hashtables aren't being built. That's surprising: I would have thought any errors that interfered with initialization would have blown up the whole process.

It's very difficult to guess what's going on. Would you feel comfortable sending me your ebdb file? I could provide you with a function to anonymize names and email addresses.

swflint commented 7 years ago

Sure, if you give me that function, I'm willing.

girzel commented 7 years ago

Okay, this should do the trick. First make a copy of your database file, then run this function on that copy. Don't run it on the original, obviously, as this overwrites the file. Please send to eric at ericabrahamsen dot net. Thanks!

(defun ebdb-anonymize-db (f)
  (interactive "fEBDB database file: ")
  (message "Loading database")
  (let ((obj (eieio-persistent-read f)))
    (setf (slot-value obj 'file) f)
    (dolist (rec (slot-value obj 'records))
      (with-slots (mail name) rec
    (when mail
      (dolist (m mail)
        (setf (slot-value m 'mail)
          (replace-regexp-in-string
           "[^@.]" "m" (slot-value m 'mail)))))
    (if (object-of-class-p rec 'ebdb-record-person)
        (with-slots (given-names surname) name
          (when surname
        (setf surname
              (replace-regexp-in-string
               "[[:graph:]]" "n" surname)))
          (setf given-names
            (mapcar (lambda (el)
                  (replace-regexp-in-string
                   "[[:graph:]]" "n" el))
                given-names))
          (let ((orgs (slot-value rec 'organizations)))
        (dolist (role orgs)
          (when (slot-value role 'mail)
            (setf (slot-value (slot-value role 'mail) 'mail)
              (replace-regexp-in-string
               "[^@.]" "m" (slot-value
                    (slot-value role 'mail) 'mail)))))))
      (setf (slot-value name 'name)
        (replace-regexp-in-string
         "[[:graph:]]" "n"
         (slot-value name 'name))))))
    (eieio-persistent-save obj f)
    (message "Database anonymized")))
swflint commented 7 years ago

Sent. Let me know if you haven't gotten it by tomorrow (but check spam first).

girzel commented 7 years ago

I haven't gotten your file, but in petty sure I figured out what was going on, it was a stupid experiment. I'll push a fix in a few hours.

swflint commented 7 years ago

Okay.

swflint commented 7 years ago

And it works!