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

Symbolic Paths #744

Closed
wants to merge 87 commits into from
Closed

Symbolic Paths #744

wants to merge 87 commits into from

Conversation

rgrinberg
Copy link
Member

This is my attempt at porting to symbolic paths. Putting this up while this is WIP as I'm not sure I'm going in the right direction as I think you imagined this change being simpler than it's turning out for me here.

Repeating the question from slack: I'm not sure if Path.parent should escape the build dir for paths inside the build dir.

@rgrinberg rgrinberg requested a review from a user May 4, 2018 10:04
@ghost
Copy link

ghost commented May 4, 2018

That seems fine to me, I expected the implementation of Path to change quite a bit. I think most of the complexity comes from the fact that paths inside the build directory are no longer always local and this needs to be handled correctly.

BTW, looking at how Path.kind and Path.is_local are used outside of Path, it seems that we often have two cases:

  • either a path is an external path
  • either a path is in the source tree or build directory

Before, the second class corresponded exactly to local paths, but this is no longer the case now. I think we should call this class managed paths and update the code accordingly, for instance with a Path.is_managed function.

@ghost
Copy link

ghost commented May 4, 2018

Repeating the question from slack: I'm not sure if Path.parent should escape the build dir for paths inside the build dir.

It shouldn't. If we rely on Path.parent Path.build_dir being Path.root in some part of the code, we need to update the code to stop at Path.build_dir.

Note that this can potentially break user jbuild files if they try to escape the build directory to access the source tree directly.

@rgrinberg
Copy link
Member Author

Before, the second class corresponded exactly to local paths, but this is no longer the case now. I think we should call this class managed paths and update the code accordingly, for instance with a Path.is_managed function.

I trid this change out locally and I think that it effectively obsoletes Path.is_local. I don't think there are any instances that rely on the path actually being external. Though I think there might be some cases where we can be a little more strict and explicitly check for in_source_dir vs. in_build_dir.

@rgrinberg
Copy link
Member Author

Note that this can potentially break user jbuild files if they try to escape the build directory to access the source tree directly.

Yeah, but I think that's fine. I guess we should really be preventing the user from doing this by making sure the actions don't act on source dirs.

@rgrinberg
Copy link
Member Author

It shouldn't. If we rely on Path.parent Path.build_dir being Path.root in some part of the code, we need to update the code to stop at Path.build_dir.

OK. How about we change Path.parent to be t -> t option to have a value for when we can't advance past root (with a Path.parent_exn for situations where we know this is allowed, perhaps).

@ghost
Copy link

ghost commented May 8, 2018

OK. How about we change Path.parent to be t -> t option to have a value for when we can't advance past root (with a Path.parent_exn for situations where we know this is allowed, perhaps).

That seems fine

@rgrinberg
Copy link
Member Author

Okay, so this is getting closer to completion. There's a couple of other points that I think we should handle:

  • Recognize external paths that point to the build directory in Path.of_string.

  • Change Path.relative root "_build/foobar". Currently, this will correctly change the path to a build directory but I suppose that this should only work when the build dir is under the source tree.

Back to the point with managed vs. local. Do you think we should go ahead with this change? Internally in Path we already have a Kind module that also uses a Local constructor so it's a bit confusing that Path.is_local and Kind.is_local will not agree.

@ghost
Copy link

ghost commented May 9, 2018

Yh, I think we need to make this change

@rgrinberg rgrinberg force-pushed the sym-path branch 6 times, most recently from 43b76ee to 7a6921a Compare May 12, 2018 13:52
@rgrinberg
Copy link
Member Author

Ok, @diml this is getting close. Now the build dir is allowed to be external vs. local so it should be easy to just set it to the other thing. There are still some issues with other functions (see path.mlt), but I'm planning to fix those.

if String.is_prefix s ~prefix:"_build" then (
Exn.code_error "in_source_tree: path is in build dir"
[ "s", Sexp.To_sexp.string s ]
);
Copy link
Member Author

Choose a reason for hiding this comment

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

I'll get rid of these checks, they were just useful for debugging.

@rgrinberg
Copy link
Member Author

rgrinberg commented May 14, 2018

@diml latest is issue is with regards to configurator:

Configurator also uses path functions now, so it should set the build dir before doing so. I'm thinking that we should simply pass the build dir via DUNE_CONFIGURATOR. But to do that, we should really have a way of packing multiple values into that env var via sexps. Can we get the Sexp parsing stuff moved to Usexp yet?

The above isn't actually necessary.

@rgrinberg
Copy link
Member Author

Okay so --build-dir seems to finally work so reviewing can start. Sorry for the mess, I'll tidy up things whenever they don't make sense.

The failure on 4.02.3 is reproducible, but I don't yet understand what's causing it and why bootstrap works on other versions. Any ideas here would be welcome.

@ghost
Copy link

ghost commented May 14, 2018

Maybe it's due to some change in the Unix library?

@rgrinberg
Copy link
Member Author

Maybe it's due to some change in the Unix library?

It was just a bug on my part. The only reason it was only reproducible on 4.02.3 was because that's where we used sandboxes.

@rgrinberg rgrinberg changed the title Symbolic Paths [WIP] Symbolic Paths May 14, 2018
let drop_build_dir p =
match build_dir_kind (), Kind.of_string p with
| Kind.External bd, Kind.External p ->
let open Option.O in
Copy link

Choose a reason for hiding this comment

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

This seems a bit fragile to me. Because we don't normalize external paths, we might miss cases here. Why do we need this exactly?

Copy link
Member Author

Choose a reason for hiding this comment

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

If the user does something like $ jbuilder build --build-dir /foo/bar /foo/bar/baz I'd expect the path to be resolved to a build dir.

I also think that the db file also relies on this. Though we can fix that by changing the sexp reading/writing not to erase the the constructor of Path.t.

Copy link

Choose a reason for hiding this comment

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

Yes, but what if the the user does jbuilder build --build-dir /foo//bar /foo/bar/baz?

@ghost
Copy link

ghost commented May 15, 2018

The last two uses of Path.kind in the code base looks incorrect to me. In the two cases, we now want to match on wether the path is managed or not rather than local or external.

@ghost
Copy link

ghost commented May 15, 2018

I think it would be easier to reason about the code if we have the guarantee that exactly one of the following assertion holds:

  • either the build directory is an absolute path that doesn't point inside the source tree
  • either it is relative to the source tree root

If the user passes an absolute path for the build directory, we don't check whether it points to the source tree or not.

I suggest to do the following: we implement a function similar to realpath to normalize absolute paths. If the build directory is given as an absolute path, then we pass it through realpath, we pass the workspace root through realpath as well and we compare them. If the build directory is a descendant of the root, then we convert it to a local path.

rgrinberg and others added 4 commits May 28, 2018 21:18
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
This avoids a few conversions

Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
with
| Unix.Unix_error (EEXIST, _, _) -> ()
| Unix.Unix_error (ENOENT, _, _) ->
Exn.fatalf "Cannot create external build directory %s. \
Copy link

Choose a reason for hiding this comment

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

We have External.mkdir_p now, should we use it here and in Path.mkdir_p?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not quite the same b/c mkdir_p would re-create the parents. What should this do when foo doesn't exist for example:

$ jbuilder build --build-dir /home/ocaml/foo/bar

Copy link

Choose a reason for hiding this comment

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

I would want foo to be created.

(build_dir, build_dir_prefix, set_build_dir)

module T : sig
type t = private
Copy link

Choose a reason for hiding this comment

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

Why the private?

@rgrinberg
Copy link
Member Author

rgrinberg commented May 28, 2018 via email

Jeremie Dimino added 3 commits May 28, 2018 19:27
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
=
let build_dir = Option.value ~default:"_build" build_dir in
Copy link

Choose a reason for hiding this comment

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

Why not put the default value in the Arg.(value ...)?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's because the default would have to be duplciated for bootstrap, but I'm no longer sure. I agree that making the default part of the CLI is correct.

Jeremie Dimino added 6 commits May 31, 2018 18:17
I find this confusing. If we re-enable interning, we'll need to make
sure the ordering in sets preserve the natural ordering.

Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
The previous name was not very clear

Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
@ghost ghost force-pushed the sym-path branch from ff76503 to c2d3e62 Compare May 31, 2018 18:10
|}]

(* This is not right, but kind of annoying to fix :/ *)
Path.relative (r "foo") "../_build"
Copy link
Member Author

Choose a reason for hiding this comment

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

Previously, I tried addressing this by having logic in the in_source_tree smart constructor to automatically change such paths to In_build_dir. This wasn't really necessary to make the feature work, so I dropped it. In any case, I wasn't comfortable with that approach either.

@rgrinberg
Copy link
Member Author

@diml I've read over your changes and I welcome them all. Github doesn't let me approve since I created this PR. I approve "manually".

@ghost
Copy link

ghost commented Jun 1, 2018

Ok, I pushed a couple of additional changes. I let you review them

@rgrinberg
Copy link
Member Author

Okay, looks fine.

@ghost ghost added this to the 1.0.0 milestone Jun 2, 2018
@ghost ghost assigned rgrinberg Jun 2, 2018
Jeremie Dimino added 2 commits June 2, 2018 17:58
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
Signed-off-by: Jeremie Dimino <jdimino@janestreet.com>
@rgrinberg
Copy link
Member Author

This is in master.

@rgrinberg rgrinberg closed this Jun 4, 2018
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.

1 participant