Skip to content

Fix remarks post-devkit removal#15

Merged
arvidj merged 9 commits intoahrefs:masterfrom
arvidj:aj/fix-ex-devkit-remarks
Feb 18, 2026
Merged

Fix remarks post-devkit removal#15
arvidj merged 9 commits intoahrefs:masterfrom
arvidj:aj/fix-ex-devkit-remarks

Conversation

@arvidj
Copy link
Contributor

@arvidj arvidj commented Feb 10, 2026

What

Respond to @rr0gi's remarks on #11

@arvidj arvidj force-pushed the aj/fix-ex-devkit-remarks branch from a71da34 to 9908d2c Compare February 10, 2026 09:30
bin/main.ml Outdated
let target_file = Path.project target_file in
let flags = [ Open_wronly; Open_creat; Open_trunc; Open_binary ] in
Out_channel.(with_open_gen flags 0o600 target_file (fun oc -> output_string oc contents))
Util.save_as ~path:target_file ~mode:0o600 (fun oc -> output_string oc contents)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Restored the original usage of Devkit.Files.save_as here. But the question remains as to whether all other writes of passage should be made atomic in the same manner (they weren't before I removed devkit).

Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC, this is what Storage.Secrets.encrypt_using_tmpfile is doing, so we're good there.

There are two cases of writing recipients to disk in commands.ml where we are using Out_channel.with_open_text.

I would say that we could use the same function everywhere, even if only for a matter of consistency. AFAIU, there are no downsides to having atomic writes here, right?

Fun.protect ~finally:(fun () -> try Sys.remove tmpfile with _ -> ()) (fun () -> f (tmpfile, tmpfile_oc))
Fun.protect
~finally:(fun () ->
Stdlib.close_out_noerr tmpfile_oc;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIUC, this should ensure that this function will not leak file descriptors in case f fails.

Copy link
Contributor

Choose a reason for hiding this comment

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

lgtmttbomk
(looks good to me, to the best of my knowledge)

@arvidj arvidj changed the title add [Util.save_as] modeled on Devkit's dito and use to update recips Fix remarks post-devkit removal Feb 10, 2026
@arvidj arvidj force-pushed the aj/fix-ex-devkit-remarks branch 2 times, most recently from acf204c to 84ce2f1 Compare February 10, 2026 09:49
@arvidj arvidj marked this pull request as ready for review February 10, 2026 09:50
@arvidj arvidj mentioned this pull request Feb 10, 2026
@arvidj arvidj force-pushed the aj/fix-ex-devkit-remarks branch from 84ce2f1 to 7994a7d Compare February 10, 2026 10:28
Copy link
Contributor

@thatportugueseguy thatportugueseguy left a comment

Choose a reason for hiding this comment

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

lgtm, we could probably have the atomic writes everywhere for consistency

bin/main.ml Outdated
let target_file = Path.project target_file in
let flags = [ Open_wronly; Open_creat; Open_trunc; Open_binary ] in
Out_channel.(with_open_gen flags 0o600 target_file (fun oc -> output_string oc contents))
Util.save_as ~path:target_file ~mode:0o600 (fun oc -> output_string oc contents)
Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC, this is what Storage.Secrets.encrypt_using_tmpfile is doing, so we're good there.

There are two cases of writing recipients to disk in commands.ml where we are using Out_channel.with_open_text.

I would say that we could use the same function everywhere, even if only for a matter of consistency. AFAIU, there are no downsides to having atomic writes here, right?

Fun.protect ~finally:(fun () -> try Sys.remove tmpfile with _ -> ()) (fun () -> f (tmpfile, tmpfile_oc))
Fun.protect
~finally:(fun () ->
Stdlib.close_out_noerr tmpfile_oc;
Copy link
Contributor

Choose a reason for hiding this comment

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

lgtmttbomk
(looks good to me, to the best of my knowledge)

Copy link
Contributor

Choose a reason for hiding this comment

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

i don't like the module name, but i don't have a better one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we could have just type.ml if you prefer? it's modelled on Devkit.Prelude.Fresh, where you'd have Fresh (String), now you have Abstract_type.Make (String). I don't think Fresh is particularly clear, but if you know you know. We could have a name that is reminiscent to Fresh, might make it more clear?

Copy link
Contributor

Choose a reason for hiding this comment

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

now you have Abstract_type.Make (String)

Actually you have Abstract_type.Fresh (String), that's why it probably makes me a bit icky. Also i feel like Abstract_type should be under some Utils module, or maybe under a Types one?

What do you feel about Types.Fresh (String)? I know that the Fresh is unclear at first, but after you have a name for the thing, can you use another one? 😅 In any case, this still doesn't make me happy, but i guess it's that old thing about naming in programming..

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Types.Fresh is OK for me, renamed in latest version.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would say that we could use the same function everywhere, even if only for a matter of consistency. AFAIU, there are no downsides to having atomic writes here, right?

Latest version I use save_as for the other case of writing recipient files. Except for that, couldn't find any file writes in the project.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Btw, we also have encrypt_using_tmpfile. It seems like it could be use Util.save_as.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the latest version I use save_as in encrypt_using_tmpfile.

I also move Util.save_as to Storage.save_as. I do this so that I can use it in Storage.Secrets.encrypt_using_tmpfile, and since Util depends on Storage this would induce a dependency cycle. I think I would've preferred to keep it in some separate module though, with some base functionality. Util is kind of that, but not really since it depends on Storage.

lib/util.mli Outdated
Comment on lines 8 to 9
will be renamed to [path] after [f] has succesfully terminated. Therefore this guarantee that either [filename] will
not be modified or will contain whatever [f] was writing to it as a side-effect.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
will be renamed to [path] after [f] has succesfully terminated. Therefore this guarantee that either [filename] will
not be modified or will contain whatever [f] was writing to it as a side-effect.
will be renamed to [path] after [f] has successfully terminated. Therefore, this guarantees that either [filename] will
not be modified or will contain whatever [f] was writing to it as a side-effect.

is it a side-effect? It's the intended result

Copy link
Contributor Author

Choose a reason for hiding this comment

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

see latest version. I think the original authors meant side-effect as in, "this function is not pure, it has a side-effect". but I think that is redundant, and confusing as you point out, so I removed it.

@arvidj arvidj merged commit 604d631 into ahrefs:master Feb 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants