-
Notifications
You must be signed in to change notification settings - Fork 377
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
Structify more of the internals to simplify the implementation. #911
Conversation
Reduces the number of arguments to the function signatures, making the code much easier to understand, and relocates some things. For example, `docker_in_docker` is now associated with `Engine`, and now with `cli::Args`. Likewise, unstable doctests is now a part of `Environment` and not `cli::Args`. `MessageInfo` now stores mutable state (needs to clear lines) and is no longer copyable, and a single instance is created in lib and passed around everywhere as a mutable reference. This also fixes an issue where `-vv+` was not recognized as a valid verbose flag: `cargo` can handle 1 or more `v` characters. Also allowed parsing of `--color=value` args, when we previously only accepted `--color value`.
Still a draft since many things changed and I need to triple check no bugs were introduced. This refactors a lot of things to try to simplify our logic internally. The only actual changes in terms of behavior for the user are bug fixes:
Both are consistent with |
@@ -149,6 +149,18 @@ pub enum Volumes { | |||
Remove(RemoveVolume), | |||
} | |||
|
|||
macro_rules! volumes_get_field { | |||
($self:ident, $field:ident $(.$cb:ident)?) => {{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid a lot of redundant code, I added macros so we can extract a single field from an enumeration. The callback allows to add as_deref
if needed.
} | ||
} | ||
} | ||
fn as_verbosity<T, C: Fn(&mut MessageInfo) -> T>(&mut self, call: C, new: Verbosity) -> T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added these functions so we can temporarily change the verbosity of a function call, either to silence or to be more verbose, etc. It allows us to store the old value, and return a result and ensure the old state is restored.
message!(@status stream, $status, $message, $color, $msg_info) | ||
}}; | ||
} | ||
/// prints a red 'error' message and terminates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've also moved away from free functions since we store state now.
|
||
macro_rules! get_engine { | ||
($args:ident, $docker_in_docker:expr, $msg_info: ident) => {{ | ||
get_container_engine($args.engine(), $docker_in_docker, &mut $msg_info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These macros just simplify a lot of redundant code that existed earlier, while being relatively transparent.
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn is_verbose(arg: &str) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This corrects the behavior so -vvvvv
and similar are accepted as arguments to get the verbosity. Previously this was passed to cargo
, but not correctly processed for cross
itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, was meaning to fix this myself
} | ||
} | ||
|
||
enum ArgKind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allows us to determine if the argument is the field or starts with the field in a single check, and then we can choose to process it immediately after.
@@ -167,37 +223,17 @@ pub fn parse(target_list: &TargetList) -> Result<Args> { | |||
} | |||
} | |||
|
|||
let msg_info = shell::MessageInfo::create(verbose, quiet, color.as_deref())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a single instance, so it's been moved to lib
.
@@ -167,37 +223,17 @@ pub fn parse(target_list: &TargetList) -> Result<Args> { | |||
} | |||
} | |||
|
|||
let msg_info = shell::MessageInfo::create(verbose, quiet, color.as_deref())?; | |||
let docker_in_docker = if let Ok(value) = env::var("CROSS_CONTAINER_IN_CONTAINER") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a CLI argument, so it's been moved to Engine
.
false | ||
}; | ||
|
||
let enable_doctests = env::var("CROSS_UNSTABLE_ENABLE_DOCTESTS") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a CLI argument, so this has been moved to config
.
.ok() | ||
} | ||
|
||
fn custom_toolchain(&self) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better we don't process all our config options for environment variables in lib
itself, since variables like this are part of the configuration.
@@ -22,27 +22,38 @@ pub enum EngineType { | |||
pub struct Engine { | |||
pub kind: EngineType, | |||
pub path: PathBuf, | |||
pub in_docker: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docker_in_docker
is natural here, since it's part of the behavior of the engine. We also only need it to determine the mount finder, so it's a good place.
Great! looks like a straightforward interface improvement |
pub(crate) fn run( | ||
engine: &Engine, | ||
target: &Target, | ||
options: DockerOptions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restructuring into 2 logical structs simplifies our function signatures a lot, especially in docker::run
and the like.
src/docker/local.rs
Outdated
.wrap_err("when copying seccomp profile")?; | ||
docker_user_id(&mut docker, engine.kind); | ||
docker_seccomp( | ||
&mut docker, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried not to overly rely on just having the structs passed: if there's any question of if the logic could need to be accessed outside and the logic does not rely on most of the members or it would require a lot of work to create those members, I've avoided passing the struct itself.
struct DeleteVolume<'a>(&'a Engine, &'a VolumeId, MessageInfo); | ||
// it's unlikely that we ever need to erase a line in the destructors, | ||
// and it's better than keep global state everywhere, or keeping a ref | ||
// cell which could have already deleted a line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deleters are the only location we don't have a single instance of MessageInfo
, but I think this is fine since it avoids having to pass a RefCell
everywhere, worrying about avoiding multiple mutable borrows, etc., and the chance we delete a line when invoking the deleters is near 0.
fn print(&self, msg_info: MessageInfo) -> Result<()> { | ||
shell::print(&self.fmt_message(msg_info), msg_info) | ||
fn print(&self, msg_info: &mut MessageInfo) -> Result<()> { | ||
let msg = self.fmt_message(msg_info); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be in 2 steps to avoid multiple mutable borrows.
@@ -338,7 +338,7 @@ impl From<Host> for Target { | |||
Host::Aarch64UnknownLinuxMusl => Target::new_built_in("aarch64-unknown-linux-musl"), | |||
Host::Other(s) => Target::from( | |||
s.as_str(), | |||
&rustc::target_list(Verbosity::Quiet.into()).unwrap(), | |||
&rustc::target_list(&mut Verbosity::Quiet.into()).unwrap(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again, we will never need to delete a line from the output here, so this isn't an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bors r+
Build succeeded: |
Reduces the number of arguments to the function signatures, making the code much easier to understand, and relocates some things. For example,
docker_in_docker
is now associated withEngine
, and now withcli::Args
. Likewise, unstable doctests is now a part ofEnvironment
and notcli::Args
.MessageInfo
now stores mutable state (needs to clear lines) and is no longer copyable, and a single instance is created in lib and passed around everywhere as a mutable reference.The changes with
MessageInfo
will allow us to erase lines in the future, both fromstderr
andstdout
, which we currently don't use but will allow us to close #859.This also fixes an issue where
-vv+
was not recognized as a valid verbose flag:cargo
can handle 1 or morev
characters. Also allowed parsing of--color=value
args, when we previously only accepted--color value
.