* [BUG] ob-tangle.el: Blocks overwrite each other when grouping before tangling @ 2023-07-12 20:59 Evgenii Klimov 2023-07-12 22:51 ` [PATCH] " Evgenii Klimov 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-12 20:59 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 2512 bytes --] Hi, I noticed that during grouping of blocks to tangle some of them can overwrite each other if they have the same target file, but in different format (relative vs absolute). Consider this example (part of example.org file in the attachment): * 1st explicit :tangle yes #+begin_src emacs-lisp :tangle yes "1st explicit :tangle yes" #+end_src * 1st implicit default #+begin_src emacs-lisp "1st implicit :tangle no" #+end_src If we call `org-babel-tangle-file' with target-file arg equal to "/path/to/example.el" (e.g. `org-babel-load-file' does that), then target file name for the first block will be "example.el" and "/path/to/example.el" for the second block. It appears to be crucial in `org-babel-tangle-collect-blocks' [1]: ;; `org-babel-map-src-blocks' runs this part on each source block (let* ((block (org-babel-tangle-single-block counter)) (src-tfile (cdr (assq :tangle (nth 4 block)))) (file-name (org-babel-effective-tangled-filename (nth 1 block) src-lang src-tfile)) (by-fn (assoc file-name blocks))) (if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn))) (push (cons file-name (list (cons src-lang block))) blocks))) Current implementation of `org-babel-effective-tangled-filename' returns relative file name if :tangle is "yes" or relative FILENAME. But if :tangle happened to be absolute (as `org-babel-load-file' does), then blocks with the same file name but one name is relative while the other is absolute, will be treated as different and won't be group (see last tree lines of code above). As a result when blocks are returned to `org-babel-tangle' [2] one group will overwrite the previous one, since their absolute file names are equal. I noticed two scenarious where such things happen (e.g. if running `org-babel-tangle-file'): - if target-file arg is equal to one of :tangle FILENAMEs and some blocks don't have :tangle argument, while other have :tangle FILENAME. As a result one of these groups will be lost. - if target-file arg is equal to tangled original Org file and some blocks don't have :tangle argument, while other have :tangle "yes". As a result one of these groups will also be lost. I attach example Org file and scratch code to reproduce both scenarious. [1] [[file:lisp/ob-tangle.el::(file-name (org-babel-effective-tangled-filename][target file-name]] [2] [[file:lisp/ob-tangle.el::org-babel-tangle-collect-blocks lang-re tangle-file))][blocks return]] [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: example Org file --] [-- Type: text/x-org, Size: 710 bytes --] * 1st explicit :tangle yes #+begin_src emacs-lisp :tangle yes "1st explicit :tangle yes" #+end_src * 1st explicit :tangle filename.el #+begin_src emacs-lisp :tangle filename.el "1st explicit :tangle filename.el" #+end_src * 1st implicit default #+begin_src emacs-lisp "1st implicit :tangle no" #+end_src * 2nd explicit :tangle yes #+begin_src emacs-lisp :tangle yes "2nd explicit :tangle yes" #+end_src * explicit :tangle no #+begin_src emacs-lisp :tangle no "explicit :tangle no" #+end_src * 2nd explicit :tangle filename.el #+begin_src emacs-lisp :tangle filename.el "2nd explicit :tangle filename.el" #+end_src * 2nd implicit default #+begin_src emacs-lisp "2nd implicit :tangle no" #+end_src [-- Attachment #3: scratch code to reproduce the bug --] [-- Type: application/emacs-lisp, Size: 706 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-12 20:59 [BUG] ob-tangle.el: Blocks overwrite each other when grouping before tangling Evgenii Klimov @ 2023-07-12 22:51 ` Evgenii Klimov 2023-07-13 10:52 ` [PATCH v2] " Evgenii Klimov 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-12 22:51 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 32 bytes --] And here's the patch to fix it. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0001-ob-tangle.el-Avoid-relative-file-names-when-grouping.patch --] [-- Type: text/x-diff, Size: 2457 bytes --] From 2695d48f265a4100a9fc25c4dd278ab2b4b89ba5 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Wed, 12 Jul 2023 19:24:48 +0100 Subject: [PATCH] ob-tangle.el: Avoid relative file names when grouping blocks to tangle * lisp/ob-tangle.el (org-babel-effective-tangled-filename): Avoid using relative file names that could cause one block to overwrite the others in `org-babel-tangle-collect-blocks' if they have the same target file but in different formats. --- lisp/ob-tangle.el | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index 25129616f..4aab453e3 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -427,17 +427,23 @@ that the appropriate major-mode is set. SPEC has the form: org-babel-tangle-comment-format-end link-data))))) (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) - "Return effective tangled filename of a source-code block. + "Return effective tangled absolute filename of a source-code block. BUFFER-FN is the name of the buffer, SRC-LANG the language of the block and SRC-TFILE is the value of the :tangle header argument, as computed by `org-babel-tangle-single-block'." - (let ((base-name (cond - ((string= "yes" src-tfile) - ;; Use the buffer name - (file-name-sans-extension buffer-fn)) - ((string= "no" src-tfile) nil) - ((> (length src-tfile) 0) src-tfile))) - (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) + (let* ((fnd (file-name-directory (buffer-file-name + (get-buffer buffer-fn)))) + (base-name (cond + ((string= "yes" src-tfile) + ;; Use the buffer name + (file-name-concat fnd + (file-name-sans-extension buffer-fn))) + ((string= "no" src-tfile) nil) + ((> (length src-tfile) 0) + (if (file-name-directory src-tfile) + src-tfile + (file-name-concat fnd src-tfile))))) + (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) (when base-name ;; decide if we want to add ext to base-name (if (and ext (string= "yes" src-tfile)) -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-12 22:51 ` [PATCH] " Evgenii Klimov @ 2023-07-13 10:52 ` Evgenii Klimov 2023-07-14 8:45 ` Ihor Radchenko 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-13 10:52 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 216 bytes --] In this version I just updated the docstrings for the relevant functions, because prior to that it wasn't clear: does this "default export file for *all* source blocks" influence blocks with :tangle "yes"/FILENAME? [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: v2-0001-ob-tangle.el-Avoid-relative-file-names-when-group.patch --] [-- Type: text/x-diff, Size: 3894 bytes --] From 1a4f76960cf11fb192f2bee2cdc8778c7b897f1a Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Wed, 12 Jul 2023 19:24:48 +0100 Subject: [PATCH v2] ob-tangle.el: Avoid relative file names when grouping blocks to tangle * lisp/ob-tangle.el (org-babel-effective-tangled-filename): Avoid using relative file names that could cause one block to overwrite the others in `org-babel-tangle-collect-blocks' if they have the same target file but in different formats. (org-babel-tangle-file, org-babel-tangle): Clarify the meaning of the TARGET-FILE argument. --- lisp/ob-tangle.el | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index 25129616f..1274d0db7 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -194,11 +194,12 @@ evaluating BODY." ;;;###autoload (defun org-babel-tangle-file (file &optional target-file lang-re) - "Extract the bodies of source code blocks in FILE. + "Extract the bodies of source code blocks from FILE. Source code blocks are extracted with `org-babel-tangle'. Optional argument TARGET-FILE can be used to specify a default -export file for all source blocks. +export file for all source blocks without :tangle header +argument. Optional argument LANG-RE can be used to limit the exported source code blocks by languages matching a regular expression. @@ -230,9 +231,10 @@ With one universal prefix argument, only tangle the block at point. When two universal prefix arguments, only tangle blocks for the tangle file of the block at point. Optional argument TARGET-FILE can be used to specify a default -export file for all source blocks. Optional argument LANG-RE can -be used to limit the exported source code blocks by languages -matching a regular expression." +export file for all source blocks without :tangle header +argument. Optional argument LANG-RE can be used to limit the +exported source code blocks by languages matching a regular +expression." (interactive "P") (run-hooks 'org-babel-pre-tangle-hook) ;; Possibly Restrict the buffer to the current code block @@ -427,17 +429,23 @@ that the appropriate major-mode is set. SPEC has the form: org-babel-tangle-comment-format-end link-data))))) (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) - "Return effective tangled filename of a source-code block. + "Return effective tangled absolute filename of a source-code block. BUFFER-FN is the name of the buffer, SRC-LANG the language of the block and SRC-TFILE is the value of the :tangle header argument, as computed by `org-babel-tangle-single-block'." - (let ((base-name (cond - ((string= "yes" src-tfile) - ;; Use the buffer name - (file-name-sans-extension buffer-fn)) - ((string= "no" src-tfile) nil) - ((> (length src-tfile) 0) src-tfile))) - (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) + (let* ((fnd (file-name-directory (buffer-file-name + (get-buffer buffer-fn)))) + (base-name (cond + ((string= "yes" src-tfile) + ;; Use the buffer name + (file-name-concat fnd + (file-name-sans-extension buffer-fn))) + ((string= "no" src-tfile) nil) + ((> (length src-tfile) 0) + (if (file-name-directory src-tfile) + src-tfile + (file-name-concat fnd src-tfile))))) + (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) (when base-name ;; decide if we want to add ext to base-name (if (and ext (string= "yes" src-tfile)) -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-13 10:52 ` [PATCH v2] " Evgenii Klimov @ 2023-07-14 8:45 ` Ihor Radchenko 2023-07-24 12:28 ` [PATCH v3] " Evgenii Klimov 0 siblings, 1 reply; 10+ messages in thread From: Ihor Radchenko @ 2023-07-14 8:45 UTC (permalink / raw) To: Evgenii Klimov; +Cc: emacs-orgmode Evgenii Klimov <eugene.dev@lipklim.org> writes: > In this version I just updated the docstrings for the relevant > functions, because prior to that it wasn't clear: does this "default > export file for *all* source blocks" influence blocks with :tangle > "yes"/FILENAME? Thanks for the patch, but we need to be careful changing things in ob-tangle. Not everything is well-documented there. > Optional argument TARGET-FILE can be used to specify a default > -export file for all source blocks. > +export file for all source blocks without :tangle header > +argument. This is confusing. Is :tangle yes "without"? What about inheritance? What about default header args? What if we have :tangle "/path/to/foo" and TARGET-FILE = "/path/to/foo"? What if they are :tangle "./foo" and TARGET-FILE = "/full/path/to/foo"? > (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) > - "Return effective tangled filename of a source-code block. > + "Return effective tangled absolute filename of a source-code block. This will likely cause breakage. There are two callers of `org-babel-effective-tangled-filename: 1. `org-babel-tangle-collect-blocks' 2. `org-babel-tangle-single-block' `org-babel-tangle-single-block' passes (nth 1 result) as BUFFER-FN. Its value is (if org-babel-tangle-use-relative-file-links (file-relative-name file) file) So, > + (let* ((fnd (file-name-directory (buffer-file-name > + (get-buffer buffer-fn)))) will fail when FILE contains file path. And it does: (file (buffer-file-name (buffer-base-buffer))) -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-14 8:45 ` Ihor Radchenko @ 2023-07-24 12:28 ` Evgenii Klimov 2023-07-25 7:02 ` Ihor Radchenko 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-24 12:28 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 3079 bytes --] Hi Here are the new tests that demonstrate the bug in block grouping during block collection, along with the patch to address the issue, taking your previous remarks into account. I split it into two patches so you can apply the tests first to see the bug. And probably tests should be rewritten as they look too complex and mostly duplicate each other. I'd appreciate your suggestions on how to enhance them. Ihor Radchenko <yantar92@posteo.net> writes: > Evgenii Klimov <eugene.dev@lipklim.org> writes: > >> In this version I just updated the docstrings for the relevant >> functions, because prior to that it wasn't clear: does this "default >> export file for *all* source blocks" influence blocks with :tangle >> "yes"/FILENAME? > > Thanks for the patch, but we need to be careful changing things in > ob-tangle. Not everything is well-documented there. > >> Optional argument TARGET-FILE can be used to specify a default >> -export file for all source blocks. >> +export file for all source blocks without :tangle header >> +argument. > > This is confusing. > Is :tangle yes "without"? > What about inheritance? > What about default header args? I just find current lack of details confusing as well and want to express the place of TARGET-FILE in the lineage of :tangle in ~org-babel-get-src-block-info~: 1. org-babel-default-header-args 1. TANGLE-FILE of ~org-babel-tangle~ 2. org-babel-default-header-args:<lang> 3. org-babel-params-from-properties 4. org-element-property :parameters datum 5. org-element-property :header datum It wasn't clear for me: will ":tangle yes" or explicit ":tangle no" be affected by TARGET-FILE. Maybe if we rephrase as follows it will be clear for both of us: Optional argument TARGET-FILE can be used to overwrite a default export file in `org-babel-default-header-args' for all source blocks. > What if we have :tangle "/path/to/foo" and TARGET-FILE = "/path/to/foo"? > What if they are :tangle "./foo" and TARGET-FILE = "/full/path/to/foo"? See the new tests in the patch, I tried to take it into account. >> (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) >> - "Return effective tangled filename of a source-code block. >> + "Return effective tangled absolute filename of a source-code block. > > This will likely cause breakage. > There are two callers of `org-babel-effective-tangled-filename: > 1. `org-babel-tangle-collect-blocks' > 2. `org-babel-tangle-single-block' > > `org-babel-tangle-single-block' passes (nth 1 result) as BUFFER-FN. > Its value is > > (if org-babel-tangle-use-relative-file-links > (file-relative-name file) > file) > > So, > >> + (let* ((fnd (file-name-directory (buffer-file-name >> + (get-buffer buffer-fn)))) > > will fail when FILE contains file path. > And it does: (file (buffer-file-name (buffer-base-buffer))) Thanks, fixed: both `org-babel-tangle-single-block' and `org-babel-tangle-collect-blocks' now pass absolute value to `org-babel-effective-tangled-filename'. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: v3-0001-testing-lisp-test-ob-tangle.el-Test-block-collect.patch --] [-- Type: text/x-diff, Size: 6493 bytes --] From 7235bf0306d12f6644838ad8542ac8822bcde258 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Fri, 21 Jul 2023 22:40:06 +0100 Subject: [PATCH v3 1/2] testing/lisp/test-ob-tangle.el: Test block collection into groups for tangling * testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test block collection into groups for tangling. (ob-tangle/collect-blocks-with-target-file): The same but with TARGET-FILE. --- testing/examples/babel.org | 75 ++++++++++++++++++++++++++++++++++ testing/lisp/test-ob-tangle.el | 60 +++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/testing/examples/babel.org b/testing/examples/babel.org index d46afeb5e..2d7b39d4e 100644 --- a/testing/examples/babel.org +++ b/testing/examples/babel.org @@ -490,3 +490,78 @@ The =[[= causes a false positive which ~org-babel-detangle~ should handle proper :END: #+begin_src emacs-lisp :tangle yes :comments link #+end_src +* tangle collect blocks +:PROPERTIES: +:ID: fae6bb5b-555a-4d68-9658-a30ac5d1b2ba +:END: +** with :tangle in properties +:PROPERTIES: +:ID: b2021d51-253c-4b26-9988-dac9193eb00b +:header-args: :tangle relative.el +:END: +#+begin_src emacs-lisp +"H1: no :tangle, but :tangle relative.el in properties" +#+end_src + +#+begin_src emacs-lisp :tangle yes +"H1: :tangle yes (to babel.el)" +#+end_src + +#+begin_src emacs-lisp :tangle no +"H1: should be ignored" +#+end_src + +#+begin_src emacs-lisp :tangle ./babel.el +"H1: :tangle ./babel.el" +#+end_src + +#+begin_src emacs-lisp :tangle relative.el +"H1: :tangle relative.el" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +"H1: :tangle ./relative.el" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +"H1: :tangle /tmp/absolute.el" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +"H1: :tangle ~/../../tmp/absolute.el" +#+end_src +** without :tangle in properties +:PROPERTIES: +:ID: 9f9afb0e-ba6d-4f63-9735-71af48ecd4e6 +:END: +#+begin_src emacs-lisp +"H2: no :tangle" +#+end_src + +#+begin_src emacs-lisp :tangle yes +"H2: :tangle yes (to babel.el)" +#+end_src + +#+begin_src emacs-lisp :tangle no +"H2: should be ignored" +#+end_src + +#+begin_src emacs-lisp :tangle babel.el +"H2: :tangle babel.el" +#+end_src + +#+begin_src emacs-lisp :tangle relative.el +"H2: :tangle relative.el" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +"H2: :tangle ./relative.el" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +"H2: :tangle /tmp/absolute.el" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +"H2: :tangle ~/../../tmp/absolute.el" +#+end_src diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index 07e75f4d3..09eeffed7 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -569,6 +569,66 @@ another block (set-buffer-modified-p nil)) (kill-buffer buffer)))) +(ert-deftest ob-tangle/collect-blocks () + "Test block collection into groups for tangling." + (org-test-at-id "fae6bb5b-555a-4d68-9658-a30ac5d1b2ba" + (org-narrow-to-subtree) + (let ((expected-targets (cons '("/tmp/absolute.el" . 4) + (map-apply + (lambda (file numblocks) + (cons (expand-file-name file + org-test-example-dir) + numblocks)) + '(("relative.el" . 5) ("babel.el" . 4))))) + (collected-blocks (org-babel-tangle-collect-blocks))) + (should (= (length expected-targets) + (length (map-keys collected-blocks)))) + (let ((collected-targets (map-apply (lambda (file blocks) ; full blocks itself + (cons (expand-file-name file + org-test-example-dir) + (length blocks))) + collected-blocks))) + (should (equal (length expected-targets) + (length (map-filter + (lambda (file numblocks) + (= numblocks + (cdr (assoc-string file collected-targets)))) + expected-targets)))))))) + +(ert-deftest ob-tangle/collect-blocks-with-target-file () + "Test block collection into groups for tangling with TARGET-FILE +as `org-babel-tangle' would do." + (org-test-at-id "fae6bb5b-555a-4d68-9658-a30ac5d1b2ba" + (org-narrow-to-subtree) + (let* ((expected-targets (cons '("/tmp/absolute.el" . 4) + (map-apply + (lambda (file numblocks) + (cons (expand-file-name file + org-test-example-dir) + numblocks)) + '(("relative.el" . 5) ("babel.el" . 5))))) + ;; simulate `org-babel-tangle' and `org-babel-load-file' + ;; TARGET-FILE + (org-babel-default-header-args + (org-babel-merge-params + org-babel-default-header-args + (list (cons :tangle + (expand-file-name "babel.el" org-test-example-dir))))) + (collected-blocks (org-babel-tangle-collect-blocks))) + (should (= (length expected-targets) + (length (map-keys collected-blocks)))) + (let ((collected-targets (map-apply (lambda (file blocks) ; full blocks itself + (cons (expand-file-name file + org-test-example-dir) + (length blocks))) + collected-blocks))) + (should (equal (length expected-targets) + (length (map-filter + (lambda (file numblocks) + (= numblocks + (cdr (assoc-string file collected-targets)))) + expected-targets)))))))) + (provide 'test-ob-tangle) ;;; test-ob-tangle.el ends here -- 2.34.1 [-- Attachment #3: /home/eugene/git/org-mode/patches/v3-0002-ob-tangle.el-Avoid-relative-file-names-when-group.patch --] [-- Type: message/external-body, Size: 103 bytes --] ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-24 12:28 ` [PATCH v3] " Evgenii Klimov @ 2023-07-25 7:02 ` Ihor Radchenko 2023-07-25 16:12 ` [PATCH v4] " Evgenii Klimov 0 siblings, 1 reply; 10+ messages in thread From: Ihor Radchenko @ 2023-07-25 7:02 UTC (permalink / raw) To: Evgenii Klimov; +Cc: emacs-orgmode Evgenii Klimov <eugene.dev@lipklim.org> writes: > Here are the new tests that demonstrate the bug in block grouping during > block collection, along with the patch to address the issue, taking your > previous remarks into account. Thanks! The second patch is malformed. May you please resend? (You can see the problem if you try to download the second patch in <https://list.orgmode.org/87bkg1h4q3.fsf@lipklim.org/T/#u>) > I split it into two patches so you can apply the tests first to see the > bug. And probably tests should be rewritten as they look too complex > and mostly duplicate each other. I'd appreciate your suggestions > on how to enhance them. If you can, please avoid using `org-test-at-id'. This is much less readable compared to explicit org-test-with-temp-text because one needs to reach out to another file in order to understand what the test is about. >>> Optional argument TARGET-FILE can be used to specify a default >>> -export file for all source blocks. >>> +export file for all source blocks without :tangle header >>> +argument. >> >> This is confusing. >> Is :tangle yes "without"? >> What about inheritance? >> What about default header args? > > I just find current lack of details confusing as well and want to > express the place of TARGET-FILE in the lineage of :tangle in > ~org-babel-get-src-block-info~: > 1. org-babel-default-header-args > 1. TANGLE-FILE of ~org-babel-tangle~ > 2. org-babel-default-header-args:<lang> > 3. org-babel-params-from-properties > 4. org-element-property :parameters datum > 5. org-element-property :header datum > > It wasn't clear for me: will ":tangle yes" or explicit ":tangle no" be > affected by TARGET-FILE. Maybe if we rephrase as follows it will be > clear for both of us: > > Optional argument TARGET-FILE can be used to overwrite a default > export file in `org-babel-default-header-args' for all source > blocks. In `org-babel-tangle', TARGET-FILE is set as fallback value for the blocks that have no :tangle value at all, including inherited; including :tangle yes. The manual asserts ‘yes’ Export the code block to source file. The file name for the source file is derived from the name of the Org file, and the file extension is derived from the source code language identifier. Example: ‘:tangle yes’. So, "yes" should imply :tangle <Org file name.lang-ext> `org-babel-tangle-collect-blocks' handles this by (unless (or (string= src-tfile "no") (and tangle-file (not (equal tangle-file src-tfile))) (and lang-re (not (string-match-p lang-re src-lang)))) So, :tangle no is always excluded. When TANGLE-FILE is set and not equal to :tangle value (including "yes"), block is also excluded. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-25 7:02 ` Ihor Radchenko @ 2023-07-25 16:12 ` Evgenii Klimov 2023-07-26 7:20 ` Ihor Radchenko 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-25 16:12 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 2354 bytes --] Ihor Radchenko <yantar92@posteo.net> writes: [...] > Thanks! > The second patch is malformed. May you please resend? Sorry, resend with rewritten test. [...] > If you can, please avoid using `org-test-at-id'. This is much less > readable compared to explicit org-test-with-temp-text because one needs > to reach out to another file in order to understand what the test is > about. Now it's less verbose, handles both cases (with and without TARGET-FILE) and prints detailed ert explanation. > Evgenii Klimov <eugene.dev@lipklim.org> writes: [...] >> It wasn't clear for me: will ":tangle yes" or explicit ":tangle no" be >> affected by TARGET-FILE. Maybe if we rephrase as follows it will be >> clear for both of us: >> >> Optional argument TARGET-FILE can be used to overwrite a default >> export file in `org-babel-default-header-args' for all source >> blocks. > > In `org-babel-tangle', TARGET-FILE is set as fallback value for the > blocks that have no :tangle value at all, including inherited; including > :tangle yes. This exactly idea I wanted to add to the docstring. > The manual asserts > > ‘yes’ > Export the code block to source file. The file name for the source > file is derived from the name of the Org file, and the file > extension is derived from the source code language identifier. > Example: ‘:tangle yes’. > > So, "yes" should imply :tangle <Org file name.lang-ext> > > `org-babel-tangle-collect-blocks' handles this by > > (unless (or (string= src-tfile "no") > (and tangle-file (not (equal tangle-file src-tfile))) > (and lang-re (not (string-match-p lang-re src-lang)))) > > So, :tangle no is always excluded. > When TANGLE-FILE is set and not equal to :tangle value (including > "yes"), block is also excluded. Indeed, but later ‘no’ The *default*. Do not extract the code in a source code file. Example: ‘:tangle no’. in conjunction with TARGET-FILE's description in ~org-babel-tangle~ docstring: Optional argument TARGET-FILE can be used to specify a *default* export file for all source blocks. made me feel doubt about TARGET-FILE's effect. Anyway, probably it was my incorrect interpretation, so let's leave it as it is. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: v4-0001-testing-lisp-test-ob-tangle.el-Test-block-collect.patch --] [-- Type: text/x-diff, Size: 4599 bytes --] From a5b4faec9b58b8e56512c03e4f1a1fe295900d3f Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Fri, 21 Jul 2023 22:40:06 +0100 Subject: [PATCH v4 1/2] testing/lisp/test-ob-tangle.el: Test block collection into groups for tangling * testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test block collection into groups for tangling. --- testing/lisp/test-ob-tangle.el | 111 +++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index 07e75f4d3..55e1f7aa3 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -569,6 +569,117 @@ another block (set-buffer-modified-p nil)) (kill-buffer buffer)))) +(ert-deftest ob-tangle/collect-blocks () + "Test block collection into groups for tangling." + (org-test-with-temp-text-in-file + "* H1 with :tangle in properties +:PROPERTIES: +:header-args: :tangle relative.el +:END: + +#+begin_src emacs-lisp +\"H1: inherited :tangle relative.el in properties\" +#+end_src + +#+begin_src emacs-lisp :tangle yes +\"H1: :tangle yes\" +#+end_src + +#+begin_src emacs-lisp :tangle no +\"H1: should be ignored\" +#+end_src + +<point> + +#+begin_src emacs-lisp :tangle relative.el +\"H1: :tangle relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +\"H1: :tangle ./relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +\"H1: :tangle /tmp/absolute.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +\"H1: :tangle ~/../../tmp/absolute.el\" +#+end_src + +* H2 without :tangle in properties + +#+begin_src emacs-lisp +\"H2: without :tangle\" +#+end_src + +#+begin_src emacs-lisp :tangle yes +\"H2: :tangle yes\" +#+end_src + +#+begin_src emacs-lisp :tangle no +\"H2: should be ignored\" +#+end_src + +#+begin_src emacs-lisp :tangle relative.el +\"H2: :tangle relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +\"H2: :tangle ./relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +\"H2: :tangle /tmp/absolute.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +\"H2: :tangle ~/../../tmp/absolute.el\" +#+end_src +" + (letrec ((org-file (buffer-file-name)) + (test-dir (file-name-directory org-file)) + (el-file-abs (concat (file-name-sans-extension org-file) ".el")) + (el-file-rel (file-name-nondirectory el-file-abs)) + (sort-fn (lambda (lst) (seq-sort-by #'car #'string-lessp lst))) + (expected-targets-fn + (lambda (nblocks-el-file) + "Convert to absolute file names and sort expected targets" + (funcall sort-fn + (map-apply (lambda (file nblocks) + (cons (expand-file-name file test-dir) nblocks)) + `(("/tmp/absolute.el" . 4) + ("relative.el" . 5) + ;; single file that differs between tests + (,el-file-abs . ,nblocks-el-file)))))) + (collected-targets-fn + (lambda (collected-blocks) + (funcall sort-fn (map-apply (lambda (file blocks) + (cons file (length blocks))) + collected-blocks))))) + ;; to the first header + (insert (format "#+begin_src emacs-lisp :tangle %s +\"H1: absolute org-file.lang-ext :tangle %s\" +#+end_src" el-file-abs el-file-abs)) + (goto-char (point-max)) + ;; to the second header + (insert (format " +#+begin_src emacs-lisp :tangle %s +\"H2: relative org-file.lang-ext :tangle %s\" +#+end_src" el-file-rel el-file-rel)) + (should (equal (funcall expected-targets-fn 4) + (funcall collected-targets-fn (org-babel-tangle-collect-blocks)))) + ;; simulate TARGET-FILE to test as `org-babel-tangle' and + ;; `org-babel-load-file' would call + ;; `org-babel-tangle-collect-blocks'. + (let ((org-babel-default-header-args + (org-babel-merge-params + org-babel-default-header-args + (list (cons :tangle el-file-abs))))) + (should (equal (funcall expected-targets-fn 5) + (funcall collected-targets-fn + (org-babel-tangle-collect-blocks)))))))) + (provide 'test-ob-tangle) ;;; test-ob-tangle.el ends here -- 2.34.1 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: v4-0002-ob-tangle.el-Avoid-relative-file-names-when-group.patch --] [-- Type: text/x-diff, Size: 4006 bytes --] From 4ca26a21612df18d8ff7f71726a858501e317e00 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Wed, 12 Jul 2023 19:24:48 +0100 Subject: [PATCH v4 2/2] ob-tangle.el: Avoid relative file names when grouping blocks to tangle * lisp/ob-tangle.el (org-babel-tangle-single-block, org-babel-tangle-collect-blocks): Make target file name attribute, used internally to group blocks with identical language, to be absolute. (org-babel-effective-tangled-filename): Avoid using relative file names that could cause one block to overwrite the others in `org-babel-tangle-collect-blocks' if they have the same target file but in different formats. --- lisp/ob-tangle.el | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index b6ae4b55a..670a3dfa7 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -427,17 +427,19 @@ that the appropriate major-mode is set. SPEC has the form: org-babel-tangle-comment-format-end link-data))))) (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) - "Return effective tangled filename of a source-code block. -BUFFER-FN is the name of the buffer, SRC-LANG the language of the -block and SRC-TFILE is the value of the :tangle header argument, -as computed by `org-babel-tangle-single-block'." - (let ((base-name (cond - ((string= "yes" src-tfile) - ;; Use the buffer name - (file-name-sans-extension buffer-fn)) - ((string= "no" src-tfile) nil) - ((> (length src-tfile) 0) src-tfile))) - (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) + "Return effective tangled absolute filename of a source-code block. +BUFFER-FN is the absolute file name of the buffer, SRC-LANG the +language of the block and SRC-TFILE is the value of the :tangle +header argument, as computed by `org-babel-tangle-single-block'." + (let* ((fnd (file-name-directory buffer-fn)) + (base-name (cond + ((string= "yes" src-tfile) + ;; Use the buffer name + (file-name-sans-extension buffer-fn)) + ((string= "no" src-tfile) nil) + ((> (length src-tfile) 0) + (expand-file-name src-tfile fnd)))) + (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) (when base-name ;; decide if we want to add ext to base-name (if (and ext (string= "yes" src-tfile)) @@ -454,7 +456,9 @@ source code blocks by languages matching a regular expression. Optional argument TANGLE-FILE can be used to limit the collected code blocks by target file." - (let ((counter 0) last-heading-pos blocks) + (let ((counter 0) + (buffer-fn (buffer-file-name (buffer-base-buffer))) + last-heading-pos blocks) (org-babel-map-src-blocks (buffer-file-name) (let ((current-heading-pos (or (org-element-begin @@ -478,7 +482,7 @@ code blocks by target file." (let* ((block (org-babel-tangle-single-block counter)) (src-tfile (cdr (assq :tangle (nth 4 block)))) (file-name (org-babel-effective-tangled-filename - (nth 1 block) src-lang src-tfile)) + buffer-fn src-lang src-tfile)) (by-fn (assoc file-name blocks))) (if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn))) (push (cons file-name (list (cons src-lang block))) blocks))))))) @@ -595,7 +599,7 @@ non-nil, return the full association list to be used by comment))) (if only-this-block (let* ((file-name (org-babel-effective-tangled-filename - (nth 1 result) src-lang src-tfile))) + file src-lang src-tfile))) (list (cons file-name (list (cons src-lang result))))) result))) -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v4] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-25 16:12 ` [PATCH v4] " Evgenii Klimov @ 2023-07-26 7:20 ` Ihor Radchenko 2023-07-26 15:07 ` [PATCH v5] " Evgenii Klimov 0 siblings, 1 reply; 10+ messages in thread From: Ihor Radchenko @ 2023-07-26 7:20 UTC (permalink / raw) To: Evgenii Klimov; +Cc: emacs-orgmode Evgenii Klimov <eugene.dev@lipklim.org> writes: >> So, :tangle no is always excluded. >> When TANGLE-FILE is set and not equal to :tangle value (including >> "yes"), block is also excluded. > > Indeed, but later > > ‘no’ > The *default*. Do not extract the code in a source code file. > Example: ‘:tangle no’. > > in conjunction with TARGET-FILE's description in ~org-babel-tangle~ > docstring: > > Optional argument TARGET-FILE can be used to specify a *default* > export file for all source blocks. > > made me feel doubt about TARGET-FILE's effect. TARGET-FILE is used instead of the normal default. > +(ert-deftest ob-tangle/collect-blocks () > + "Test block collection into groups for tangling." > + (org-test-with-temp-text-in-file > + "* H1 with :tangle in properties > +:PROPERTIES: > +:header-args: :tangle relative.el > +:END: > .... > + ;; to the first header > + (insert (format "#+begin_src emacs-lisp :tangle %s > +\"H1: absolute org-file.lang-ext :tangle %s\" > +#+end_src" el-file-abs el-file-abs)) > + (goto-char (point-max)) This combination of pre-filled text and insertions is a bit disorienting. I understand why you need to insert some things only after we know the temporary Org file name, but I'd instead placed all the contents together via insert. > +#+begin_src emacs-lisp :tangle %s > +\"H2: relative org-file.lang-ext :tangle %s\" > +#+end_src" el-file-rel el-file-rel)) > + (should (equal (funcall expected-targets-fn 4) > + (funcall collected-targets-fn (org-babel-tangle-collect-blocks)))) When reading this code, I have no idea what it is trying to test. Probably something to do with function names not being descriptive. At least, a comment would help. And the magic numbers "4" and "5" have no obvious meaning. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-26 7:20 ` Ihor Radchenko @ 2023-07-26 15:07 ` Evgenii Klimov 2023-07-28 7:29 ` Ihor Radchenko 0 siblings, 1 reply; 10+ messages in thread From: Evgenii Klimov @ 2023-07-26 15:07 UTC (permalink / raw) To: Ihor Radchenko; +Cc: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 1320 bytes --] Ihor Radchenko <yantar92@posteo.net> writes: >> +(ert-deftest ob-tangle/collect-blocks () >> + "Test block collection into groups for tangling." >> + (org-test-with-temp-text-in-file >> + "* H1 with :tangle in properties >> +:PROPERTIES: >> +:header-args: :tangle relative.el >> +:END: >> .... >> + ;; to the first header >> + (insert (format "#+begin_src emacs-lisp :tangle %s >> +\"H1: absolute org-file.lang-ext :tangle %s\" >> +#+end_src" el-file-abs el-file-abs)) >> + (goto-char (point-max)) > > This combination of pre-filled text and insertions is a bit > disorienting. I understand why you need to insert some things only after > we know the temporary Org file name, but I'd instead placed all the > contents together via insert. Rewrote. >> +#+begin_src emacs-lisp :tangle %s >> +\"H2: relative org-file.lang-ext :tangle %s\" >> +#+end_src" el-file-rel el-file-rel)) >> + (should (equal (funcall expected-targets-fn 4) >> + (funcall collected-targets-fn (org-babel-tangle-collect-blocks)))) > > When reading this code, I have no idea what it is trying to test. > Probably something to do with function names not being descriptive. > At least, a comment would help. > > And the magic numbers "4" and "5" have no obvious meaning. Hope new version is cleaner. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: v5-0001-testing-lisp-test-ob-tangle.el-Test-block-collect.patch --] [-- Type: text/x-diff, Size: 5158 bytes --] From f1bf00592b1ee2bb27148fe93316cc6c1a192179 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Fri, 21 Jul 2023 22:40:06 +0100 Subject: [PATCH v5 1/2] testing/lisp/test-ob-tangle.el: Test block collection into groups for tangling * testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test block collection into groups for tangling. --- testing/lisp/test-ob-tangle.el | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index 07e75f4d3..ad0e1c29c 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -569,6 +569,122 @@ another block (set-buffer-modified-p nil)) (kill-buffer buffer)))) +(ert-deftest ob-tangle/collect-blocks () + "Test block collection into groups for tangling." + (org-test-with-temp-text-in-file "" ; filled below, it depends on temp file name + (let* ((org-file (buffer-file-name)) + (test-dir (file-name-directory org-file)) + (el-file-abs (concat (file-name-sans-extension org-file) ".el")) + (el-file-rel (file-name-nondirectory el-file-abs))) + (insert (format "* H1 with :tangle in properties +:PROPERTIES: +:header-args: :tangle relative.el +:END: + +#+begin_src emacs-lisp +\"H1: inherited :tangle relative.el in properties\" +#+end_src + +#+begin_src emacs-lisp :tangle yes +\"H1: :tangle yes\" +#+end_src + +#+begin_src emacs-lisp :tangle no +\"H1: should be ignored\" +#+end_src + +#+begin_src emacs-lisp :tangle %s +\"H1: absolute org-file.lang-ext :tangle %s\" +#+end_src + +#+begin_src emacs-lisp :tangle relative.el +\"H1: :tangle relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +\"H1: :tangle ./relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +\"H1: :tangle /tmp/absolute.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +\"H1: :tangle ~/../../tmp/absolute.el\" +#+end_src + +* H2 without :tangle in properties + +#+begin_src emacs-lisp +\"H2: without :tangle\" +#+end_src + +#+begin_src emacs-lisp :tangle yes +\"H2: :tangle yes\" +#+end_src + +#+begin_src emacs-lisp :tangle no +\"H2: should be ignored\" +#+end_src + +#+begin_src emacs-lisp :tangle %s +\"H2: relative org-file.lang-ext :tangle %s\" +#+end_src + +#+begin_src emacs-lisp :tangle relative.el +\"H2: :tangle relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ./relative.el +\"H2: :tangle ./relative.el\" +#+end_src + +#+begin_src emacs-lisp :tangle /tmp/absolute.el +\"H2: :tangle /tmp/absolute.el\" +#+end_src + +#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el +\"H2: :tangle ~/../../tmp/absolute.el\" +#+end_src" el-file-abs el-file-abs el-file-rel el-file-rel)) + (letrec ((sort-fn (lambda (lst) (seq-sort-by #'car #'string-lessp lst))) + (normalize-expected-targets-alist + (lambda (blocks-per-target-alist) + "Convert to absolute file names and sort expected targets" + (funcall sort-fn + (map-apply (lambda (file nblocks) + (cons (expand-file-name file test-dir) nblocks)) + blocks-per-target-alist)))) + (count-blocks-in-target-files + (lambda (collected-blocks) + "Get sorted alist of target file names with number of blocks in each" + (funcall sort-fn (map-apply (lambda (file blocks) + (cons file (length blocks))) + collected-blocks))))) + (should (equal (funcall normalize-expected-targets-alist + `(("/tmp/absolute.el" . 4) + ("relative.el" . 5) + ;; file name differs between tests + (,el-file-abs . 4))) + (funcall count-blocks-in-target-files + (org-babel-tangle-collect-blocks)))) + ;; Simulate TARGET-FILE to test as `org-babel-tangle' and + ;; `org-babel-load-file' would call + ;; `org-babel-tangle-collect-blocks'. + (let ((org-babel-default-header-args + (org-babel-merge-params + org-babel-default-header-args + (list (cons :tangle el-file-abs))))) + (should (equal + (funcall normalize-expected-targets-alist + `(("/tmp/absolute.el" . 4) + ("relative.el" . 5) + ;; Default :tangle header now also + ;; points to the file name derived from the name of + ;; the Org file, so 5 blocks should go there. + (,el-file-abs . 5))) + (funcall count-blocks-in-target-files + (org-babel-tangle-collect-blocks))))))))) + (provide 'test-ob-tangle) ;;; test-ob-tangle.el ends here -- 2.34.1 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #3: v5-0002-ob-tangle.el-Avoid-relative-file-names-when-group.patch --] [-- Type: text/x-diff, Size: 4006 bytes --] From 4b1fe9ac4496ebf8473a8f077762be9abea62078 Mon Sep 17 00:00:00 2001 From: Evgenii Klimov <eugene.dev@lipklim.org> Date: Wed, 12 Jul 2023 19:24:48 +0100 Subject: [PATCH v5 2/2] ob-tangle.el: Avoid relative file names when grouping blocks to tangle * lisp/ob-tangle.el (org-babel-tangle-single-block, org-babel-tangle-collect-blocks): Make target file name attribute, used internally to group blocks with identical language, to be absolute. (org-babel-effective-tangled-filename): Avoid using relative file names that could cause one block to overwrite the others in `org-babel-tangle-collect-blocks' if they have the same target file but in different formats. --- lisp/ob-tangle.el | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index b6ae4b55a..670a3dfa7 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -427,17 +427,19 @@ that the appropriate major-mode is set. SPEC has the form: org-babel-tangle-comment-format-end link-data))))) (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile) - "Return effective tangled filename of a source-code block. -BUFFER-FN is the name of the buffer, SRC-LANG the language of the -block and SRC-TFILE is the value of the :tangle header argument, -as computed by `org-babel-tangle-single-block'." - (let ((base-name (cond - ((string= "yes" src-tfile) - ;; Use the buffer name - (file-name-sans-extension buffer-fn)) - ((string= "no" src-tfile) nil) - ((> (length src-tfile) 0) src-tfile))) - (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) + "Return effective tangled absolute filename of a source-code block. +BUFFER-FN is the absolute file name of the buffer, SRC-LANG the +language of the block and SRC-TFILE is the value of the :tangle +header argument, as computed by `org-babel-tangle-single-block'." + (let* ((fnd (file-name-directory buffer-fn)) + (base-name (cond + ((string= "yes" src-tfile) + ;; Use the buffer name + (file-name-sans-extension buffer-fn)) + ((string= "no" src-tfile) nil) + ((> (length src-tfile) 0) + (expand-file-name src-tfile fnd)))) + (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang))) (when base-name ;; decide if we want to add ext to base-name (if (and ext (string= "yes" src-tfile)) @@ -454,7 +456,9 @@ source code blocks by languages matching a regular expression. Optional argument TANGLE-FILE can be used to limit the collected code blocks by target file." - (let ((counter 0) last-heading-pos blocks) + (let ((counter 0) + (buffer-fn (buffer-file-name (buffer-base-buffer))) + last-heading-pos blocks) (org-babel-map-src-blocks (buffer-file-name) (let ((current-heading-pos (or (org-element-begin @@ -478,7 +482,7 @@ code blocks by target file." (let* ((block (org-babel-tangle-single-block counter)) (src-tfile (cdr (assq :tangle (nth 4 block)))) (file-name (org-babel-effective-tangled-filename - (nth 1 block) src-lang src-tfile)) + buffer-fn src-lang src-tfile)) (by-fn (assoc file-name blocks))) (if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn))) (push (cons file-name (list (cons src-lang block))) blocks))))))) @@ -595,7 +599,7 @@ non-nil, return the full association list to be used by comment))) (if only-this-block (let* ((file-name (org-babel-effective-tangled-filename - (nth 1 result) src-lang src-tfile))) + file src-lang src-tfile))) (list (cons file-name (list (cons src-lang result))))) result))) -- 2.34.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v5] ob-tangle.el: Blocks overwrite each other when grouping before tangling 2023-07-26 15:07 ` [PATCH v5] " Evgenii Klimov @ 2023-07-28 7:29 ` Ihor Radchenko 0 siblings, 0 replies; 10+ messages in thread From: Ihor Radchenko @ 2023-07-28 7:29 UTC (permalink / raw) To: Evgenii Klimov; +Cc: emacs-orgmode Evgenii Klimov <eugene.dev@lipklim.org> writes: > Hope new version is cleaner. Thanks! Applied, onto main. With minor amendments. Fixed. https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=fcac0039a https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=3ee10d57f Amendments: https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=410cecc0e -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-07-28 7:34 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-07-12 20:59 [BUG] ob-tangle.el: Blocks overwrite each other when grouping before tangling Evgenii Klimov 2023-07-12 22:51 ` [PATCH] " Evgenii Klimov 2023-07-13 10:52 ` [PATCH v2] " Evgenii Klimov 2023-07-14 8:45 ` Ihor Radchenko 2023-07-24 12:28 ` [PATCH v3] " Evgenii Klimov 2023-07-25 7:02 ` Ihor Radchenko 2023-07-25 16:12 ` [PATCH v4] " Evgenii Klimov 2023-07-26 7:20 ` Ihor Radchenko 2023-07-26 15:07 ` [PATCH v5] " Evgenii Klimov 2023-07-28 7:29 ` Ihor Radchenko
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.