Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pkg): dune fmt missing extra files from the locks. #10951

Merged
merged 2 commits into from
Nov 18, 2024

Conversation

moyodiallo
Copy link
Collaborator

This PR follows #10947 in which we could see the reproduction of the bug from the issue #10903.

It turns out, the issue is not a race condition, the auto-locking/solve for the dev-tool save the lock files after the setup of the build. Since dune setup once in the same run, the patch files ends up missing during the build.

bin/build_cmd.ml Outdated
@@ -82,12 +82,18 @@ let run_build_system ~common ~request =
Fiber.return ())
;;

let run_build_command_poll_eager ~(common : Common.t) ~config ~request : unit =
let run_build_command_poll_eager ~pre_request ~(common : Common.t) ~config ~request : unit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no "hooks" please. They make the code unreadable.

@gridbugs
Copy link
Collaborator

I think a simpler fix is to run a separate fiber scheduler to lock ocamlformat before running the build system. E.g.:

diff --git a/bin/build_cmd.ml b/bin/build_cmd.ml
index fec619125..66cf397cb 100644
--- a/bin/build_cmd.ml
+++ b/bin/build_cmd.ml
@@ -230,20 +230,17 @@ let fmt =
       Common.Builder.set_promote builder (if no_promote then Never else Automatically)
     in
     let common, config = Common.init builder in
+    if Lazy.force Lock_dev_tool.is_enabled
+    then
+      (* Note that generating the ocamlformat lockdir here means that
+         it will be created when a user runs `dune fmt` but not when a
+         user runs `dune build @fmt`. It's important that this logic
+         remain outside of `dune build`, as `dune build` is intended
+         to only build targets, and generating a lockdir is not
+         building a target. *)
+      Scheduler.go ~common ~config (fun () ->
+        Memo.run (Lock_dev_tool.lock_ocamlformat ()));
     let request (setup : Import.Main.build_system) =
-      let open Action_builder.O in
-      let* () =
-        if Lazy.force Lock_dev_tool.is_enabled
-        then
-          (* Note that generating the ocamlformat lockdir here means
-             that it will be created when a user runs `dune fmt` but not
-             when a user runs `dune build @fmt`. It's important that
-             this logic remain outside of `dune build`, as `dune
-             build` is intended to only build targets, and generating
-             a lockdir is not building a target. *)
-          Action_builder.of_memo (Lock_dev_tool.lock_ocamlformat ())
-        else Action_builder.return ()
-      in
       let dir = Path.(relative root) (Common.prefix_target common ".") in
       Alias.in_dir ~name:Dune_rules.Alias.fmt ~recursive:true ~contexts:setup.contexts dir
       |> Alias.request

@moyodiallo
Copy link
Collaborator Author

I think a simpler fix is to run a separate fiber scheduler to lock ocamlformat before running the build system. E.g.:

I came with this idea at some point and it turns out running twice the scheduler wasn't accepted.

@rgrinberg
Copy link
Member

I think a simpler fix is to run a separate fiber scheduler to lock ocamlformat before running the build system. E.g.:

You can do this in dune fmt as long as you don't change dune build.

@moyodiallo
Copy link
Collaborator Author

A refactoring that avoid dune build @fmt to lock ocamlformat and also avoid to run the scheduler twice.

@moyodiallo
Copy link
Collaborator Author

Another last review would be great. The hooks are removed and the scheduler runs only once.

@gridbugs @rgrinberg.

bin/build_cmd.ml Outdated
if Lazy.force Lock_dev_tool.is_enabled
then
(* Note that generating the ocamlformat lockdir here means
that it will be created when a user runs `dune fmt` but not
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: can you fix the indentation here so the comment text lines up on each line

bin/build_cmd.ml Outdated
;;

let run_build_command_poll_eager
~with_lock_ocamlformat
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of introducing special behaviour into all these functions when a flag is passed. I think it muddies what was once a fairly clean interface with a special case which makes it harder to conceptualize what these functions do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. A flag is certainly better than a hook, but we should try to do better.

Copy link
Collaborator Author

@moyodiallo moyodiallo Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could at least agree upon 69ea9cf or start from that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the issue with running the scheduler multiple times? It seems like that would also solve this problem and IMO would be preferable to either a hook or a flag.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also OK to run the scheduler once because it avoid loading the project twice than having a refactoring preference.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're not going to solve this with a hook, a flag, or with running the scheduler twice, then I'm not sure what other options are possible. If/when we make solving dependencies into a build rule/action then this will become simpler. In the meantime it sounds like a flag is the least bad option. @rgrinberg how do you feel about merging this with the flag for now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the code again and I don't think this is adequate. Here's a plan that addresses most of my concerns:

  1. Remove watch mode support from fmt. There's no point to it as it's essentially racing against the user to edit source files
  2. Implement dune fmt by running the scheduler and then running the lock + build inside.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no point to it as it's essentially racing against the user to edit source files

Is it because no one using fmt on watch mode, this is not addressed before ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably nobody is using fmt in watch mode. It would be rather frustrating as it's always racing to update the file as you're editing it, possibly overwriting your changes.

@moyodiallo moyodiallo force-pushed the fix-extra-files branch 3 times, most recently from 93ffd26 to 69ea9cf Compare September 30, 2024 15:41
Copy link
Collaborator

@gridbugs gridbugs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with the flag solution provided that there's a comment explaining why it's necessary.

@moyodiallo moyodiallo force-pushed the fix-extra-files branch 2 times, most recently from ba0d481 to ad7c1f2 Compare October 3, 2024 16:03
@moyodiallo
Copy link
Collaborator Author

Refactored on the flag solution and rebased.

ping @rgrinberg.

@rgrinberg
Copy link
Member

I'll take a look tomorrow

bin/build_cmd.ml Outdated
;;

let run_build_command_poll_eager
~with_lock_ocamlformat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the code again and I don't think this is adequate. Here's a plan that addresses most of my concerns:

  1. Remove watch mode support from fmt. There's no point to it as it's essentially racing against the user to edit source files
  2. Implement dune fmt by running the scheduler and then running the lock + build inside.

@moyodiallo moyodiallo force-pushed the fix-extra-files branch 2 times, most recently from d25eea8 to bddf9d9 Compare November 5, 2024 14:50
@moyodiallo
Copy link
Collaborator Author

  1. Remove watch mode support from fmt. There's no point to it as it's essentially racing against the user to edit source files
  2. Implement dune fmt by running the scheduler and then running the lock + build inside

The 2. won't solve this issue because what we want is to run the lock and then run the scheduler.
But I've got what the suggestions 1 & 2 means in the case of the PR and some of the work is done here #11044.

The suggestions are applied.

@moyodiallo
Copy link
Collaborator Author

@gridbugs What do you think about this simplification ?

ping @rgrinberg.

Signed-off-by: Alpha DIALLO <moyodiallo@gmail.com>
Signed-off-by: Alpha DIALLO <moyodiallo@gmail.com>
@@ -55,29 +59,16 @@ Make the ocamlformat opam package which uses a patch:
Make a project that uses the fake ocamlformat:
$ make_project_with_dev_tool_lockdir

First run of 'dune fmt'
$ DUNE_CONFIG__LOCK_DEV_TOOL=enabled dune fmt 2>&1 | sed -E 's#.*.sandbox/[^/]+#.sandbox/$SANDBOX#g'
First run of 'dune fmt' is supposed to format the fail.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
First run of 'dune fmt' is supposed to format the fail.
First run of 'dune fmt' is supposed to format the file.

inside '_private/default/..' directory, since the file could not be copied, the rule is not activated.
So it fails when 'dune' trying to apply the patch. After any follwing run of 'dune fmt', it works
because the 'patch' file is already present.

The issue is now fixed.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should write this sort of comment in our tests. The test should describe the behaviour we're trying to preserve, but it's not necessary to describe the original problem or the fact that it was fixed. If anything, include a link to the github issue so people can read more about it there.

@gridbugs
Copy link
Collaborator

I'm happy with the state of this PR. I've left some comments about some minor stylistic fixes to the test.

@rgrinberg rgrinberg merged commit f975cc0 into ocaml:main Nov 18, 2024
27 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants