Discussion:
enable-local-variables and emacs --batch
Kaushal Modi
2018-11-01 14:54:02 UTC
Permalink
Hello,

I am unable to get the safe-marked variables to evaluate from
.dir-locals.el *only* when running emacs --batch.

For example, I have the below evaluated in emacs --batch --eval before
I load an Org file:

(put 'org-hugo-section 'safe-local-variable 'stringp)

And this in .dir-locals.el:

((org-mode . ((org-hugo-section . "foo"))))

But the org-hugo-section does not get set to "foo".

If I open an Org file in the directory with that .dir-locals.el in a
non-batch regular Emacs session, C-h v org-hugo-section shows that
it's set to "foo", and I get no prompts to apply/save that local
variable (as expected because I have marked it as
safe-local-variable).

So the only way I can make the .dir-locals.el apply that value is if I
do (setq enable-local-variables :all) when running emacs --batch.

But I don't consider that safe.

Why isn't the 'safe-local-variable attribute ignored only when running
emacs --batch?

My Emacs version: GNU Emacs 27.0.50 (build 34, x86_64-pc-linux-gnu,
GTK+ Version 2.24.23)
of 2018-10-31, built using commit 42681c54bf5ea2ff9d2a3ec6553766b194454caf.

Thanks.

--
Kaushal Modi
Eli Zaretskii
2018-11-03 09:16:54 UTC
Permalink
Date: Thu, 1 Nov 2018 10:54:02 -0400
I am unable to get the safe-marked variables to evaluate from
.dir-locals.el *only* when running emacs --batch.
For example, I have the below evaluated in emacs --batch --eval before
(put 'org-hugo-section 'safe-local-variable 'stringp)
((org-mode . ((org-hugo-section . "foo"))))
But the org-hugo-section does not get set to "foo".
If I open an Org file in the directory with that .dir-locals.el in a
non-batch regular Emacs session, C-h v org-hugo-section shows that
it's set to "foo", and I get no prompts to apply/save that local
variable (as expected because I have marked it as
safe-local-variable).
So the only way I can make the .dir-locals.el apply that value is if I
do (setq enable-local-variables :all) when running emacs --batch.
But I don't consider that safe.
Why isn't the 'safe-local-variable attribute ignored only when running
emacs --batch?
You didn't show any actual command you are using for the batch-mode
invocation, but my first guess would be that the file is visited
before the --eval command-line option is executed.
Kaushal Modi
2018-11-03 10:05:42 UTC
Permalink
Hello Eli,
Post by Eli Zaretskii
You didn't show any actual command you are using for the batch-mode
invocation, but my first guess would be that the file is visited
before the --eval command-line option is executed.
I made sure that --eval happened before the file load. I even have a
specific note for that:

# Note: The Org file from $(ORG_FILE) is loaded *after* the --eval
# section gets evaluated i.e. --eval '(progn ..)' $(ORG_FILE) If the
# order is reversed i.e. i.e.$(ORG_FILE) --eval '(progn ..)', the act
# of loading the $(ORG_FILE) file first will load the older Org
# version that ships with Emacs and then run the stuff in --eval that
# loads the new Org version.. and thus we'll end up with mixed Org in
# the load-path.
emacs-batch:
@echo ""
@echo "$(ORG_FILE) ::"
@$(EMACS) --batch --eval "(progn\
(setenv \"OX_HUGO_ELPA\" \"$(OX_HUGO_ELPA)\")\
(setenv \"TEST_ENABLED\" \"$(TEST_ENABLED)\")\
(load-file (expand-file-name \"setup-ox-hugo.el\" \"$(OX_HUGO_TEST_DIR)\"))\
)" $(ORG_FILE) \
-f $(FUNC) \
--kill

The setup-ox-hugo.el contains the code to load the ox-hugo package and in
there I even manually load-file the package autoloads file that contains
the elisp forms that `put' `safe-local-variable' on the defcustoms.

The $(ORG_FILE) comes after the --eval in that emacs --batch command.

The $(FUNC) is just an Org export command.

I'll work on getting a minimal reproducible example when I get to a
computer.
Eli Zaretskii
2018-11-03 10:46:42 UTC
Permalink
Date: Sat, 3 Nov 2018 06:05:42 -0400
# Note: The Org file from $(ORG_FILE) is loaded *after* the --eval
# section gets evaluated i.e. --eval '(progn ..)' $(ORG_FILE) If the
# order is reversed i.e. i.e.$(ORG_FILE) --eval '(progn ..)', the act
# of loading the $(ORG_FILE) file first will load the older Org
# version that ships with Emacs and then run the stuff in --eval that
# loads the new Org version.. and thus we'll end up with mixed Org in
# the load-path.
@echo ""
@echo "$(ORG_FILE) ::"
@$(EMACS) --batch --eval "(progn\
(setenv \"OX_HUGO_ELPA\" \"$(OX_HUGO_ELPA)\")\
(setenv \"TEST_ENABLED\" \"$(TEST_ENABLED)\")\
(load-file (expand-file-name \"setup-ox-hugo.el\" \"$(OX_HUGO_TEST_DIR)\"))\
)" $(ORG_FILE) \
-f $(FUNC) \
--kill
The setup-ox-hugo.el contains the code to load the ox-hugo package and in there I even manually load-file the
package autoloads file that contains the elisp forms that `put' `safe-local-variable' on the defcustoms.
The $(ORG_FILE) comes after the --eval in that emacs --batch command.
The $(FUNC) is just an Org export command.
I'll work on getting a minimal reproducible example when I get to a computer.
If you are going to have a small reproducer (and don't find the
problem while working on that), then why not step through the relevant
code in Edebug and see why it doesn't work?
Kaushal Modi
2018-11-03 11:18:23 UTC
Permalink
Post by Eli Zaretskii
If you are going to have a small reproducer (and don't find the
problem while working on that), then why not step through the relevant
code in Edebug and see why it doesn't work?
How can I Edebug in emacs --batch (also what to edebug?). I see that
enable-local-variables is `t' (default value), and still the
.dir-locals.el is ineffective in --batch. Otherwise, in regular emacs
sessions, the put safe-local-variable + .dir-locals.el combo works
well.

Here's a minimal example.

1. Create a temp dir
2. Create the below setup-foo.el file in there.
3. touch foo.org
4. emacs --batch --eval '(load-file "setup-foo.el")' foo.org -f echo-foo

===== setup-foo.el =====
(defconst foo nil)
(put 'foo 'safe-local-variable 'stringp)

;; Uncomment below to make the .dir-locals.el set value to apply.
;; (setq enable-local-variables :all)

(defun echo-foo ()
(message "enable-local-variables = %S" enable-local-variables)
(if (boundp 'foo)
(progn
(message "foo = %S" foo)
(if foo
(message "The value of `foo' from .dir-locals.el was applied.")
(message "The value of `foo' from .dir-locals.el was *not*
applied.")))
(message "`foo' is not defined")))
=====
Kaushal Modi
2018-11-03 11:21:52 UTC
Permalink
Post by Kaushal Modi
Here's a minimal example.
I sent that email too soon. I had a typo in that minimal example, and
after fixing that, I cannot reproduce the problem.

Should have been:

(put 'foo 'safe-local-variable 'booleanp) ;not 'stringp

But I do not have that same typo in the actual code.

Now the challenge is edebugging in --batch mode.
Kaushal Modi
2018-11-03 12:49:03 UTC
Permalink
Post by Kaushal Modi
Now the challenge is edebugging in --batch mode.
I don't know how to edebug in --batch, but I tried to used messages,
to get confused even more.

I couldn't reproduce the issue in that minimal example, so just added
debug messages to my actual code.

Below is the debug output while the .org file is opened in emacs --batch.

Debug code:

=====
(message "file: %S" (buffer-file-name))

(message "enable-local-variables = %S" enable-local-variables)
(message "org-hugo-section (safe-local-variable) = %S" (get
'org-hugo-section 'safe-local-variable))
(if-let* ((valid-dir-locals-found (dir-locals-find-file (buffer-file-name)))
(dir (if (listp valid-dir-locals-found)
(car valid-dir-locals-found)
valid-dir-locals-found)))
(message ".dir-locals.el file: %s"
(car
(dir-locals--all-files dir))))

(message "[ox-hugo section-path DBG] org-hugo-section: %S" org-hugo-section)
=====

Output:

=====
file: "/home/kmodi/stow/pub_dotfiles/emacs/dot-emacs.d/elisp/ox-hugo/test/site/content-org/dir-locals/dir-locals-test.org"
enable-local-variables = t
org-hugo-section (safe-local-variable) = stringp
.dir-locals.el file:
/home/kmodi/stow/pub_dotfiles/emacs/dot-emacs.d/elisp/ox-hugo/test/site/content-org/dir-locals/.dir-locals.el
[ox-hugo section-path DBG] org-hugo-section: "posts"
=====

Content in ..content-org/dir-locals/.dir-locals.el:

=====
((nil . ((indent-tabs-mode . nil)
(fill-column . 70)
(sentence-end-double-space . t)))
(org-mode . ((mode . auto-fill)
(org-hugo-section . "dir-locals-test")
(org-hugo-front-matter-format . "yaml")
(org-hugo-footer . "\n\nThis text is auto inserted at
the end of the exported Markdown.")
(org-hugo-preserve-filling . nil)
(org-hugo-use-code-for-kbd . t)
(org-hugo-export-with-toc . t)
(org-hugo-export-with-section-numbers . t)
(org-hugo-export-creator-string . "Dummy creator string")
(org-hugo-date-format . "%Y-%m-%d")
(org-hugo-auto-export-on-save . t))))
=====


So my confusion ..:

1. Checked that enable-local-variables is t ("enable-local-variables =
t" in debug)
2. Checked that org-hugo-section is marked as safe if it's a string
("org-hugo-section (safe-local-variable) = stringp" in debug)
3. Checked that the correct .dir-locals.el file is applied
(".dir-locals.el file:
/home/kmodi/stow/pub_dotfiles/emacs/dot-emacs.d/elisp/ox-hugo/test/site/content-org/dir-locals/.dir-locals.el"
in debug)
4. See that .dir-locals.el file above and the value of
org-hugo-section -> (org-hugo-section . "dir-locals-test") <- it is
"dir-locals-test" .. and it is a string!

But still the value read of `org-hugo-section' in that .org file
buffer is "posts"!! (in debug -> [ox-hugo section-path DBG]
org-hugo-section: "posts")

So this happens only in emacs --batch, not when I open that file
manually in a regular Emacs session.

Help?

Loading...