-
-
Notifications
You must be signed in to change notification settings - Fork 13.9k
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
Better pkgs/by-name
errors, minor fixes and improvements
#290743
Changes from 13 commits
712ac79
a61c8c9
24069b9
a53b07e
7258d47
75cdccd
db7562e
f5e9b88
eb1f014
1c4308c
ce27178
d2fa5ba
64da617
2e8d778
f056449
7858f06
5981aff
fb0a072
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -51,6 +51,23 @@ struct Location { | |||||
pub column: usize, | ||||||
} | ||||||
|
||||||
impl Location { | ||||||
// Returns the [file] field, but relative to Nixpkgs | ||||||
fn relative_file(&self, nixpkgs_path: &Path) -> anyhow::Result<PathBuf> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Future: This makes me think that Nixpkgs object ought to be passed in here, then use its |
||||||
Ok(self | ||||||
.file | ||||||
.strip_prefix(nixpkgs_path) | ||||||
.with_context(|| { | ||||||
format!( | ||||||
"The file ({}) is outside Nixpkgs ({})", | ||||||
self.file.display(), | ||||||
nixpkgs_path.display() | ||||||
) | ||||||
})? | ||||||
.to_path_buf()) | ||||||
} | ||||||
} | ||||||
|
||||||
#[derive(Deserialize)] | ||||||
pub enum AttributeVariant { | ||||||
/// The attribute is not an attribute set, we're limited in the amount of information we can get | ||||||
|
@@ -195,7 +212,6 @@ fn by_name( | |||||
use ByNameAttribute::*; | ||||||
|
||||||
let relative_package_file = structure::relative_file_for_package(attribute_name); | ||||||
let absolute_package_file = nixpkgs_path.join(&relative_package_file); | ||||||
|
||||||
// At this point we know that `pkgs/by-name/fo/foo/package.nix` has to exists. | ||||||
// This match decides whether the attribute `foo` is defined accordingly | ||||||
|
@@ -276,51 +292,86 @@ fn by_name( | |||||
// We should expect manual definitions to have a location, otherwise we can't | ||||||
// enforce the expected format | ||||||
if let Some(location) = location { | ||||||
// Parse the Nix file in the location and figure out whether it's an | ||||||
// attribute definition of the form `= callPackage <arg1> <arg2>`, | ||||||
// Parse the Nix file in the location | ||||||
let nix_file = nix_file_store.get(&location.file)?; | ||||||
|
||||||
// The relative path of the Nix file, for error messages | ||||||
let relative_file = | ||||||
location.relative_file(nixpkgs_path).with_context(|| { | ||||||
format!( | ||||||
"Failed to resolve location file of attribute {attribute_name}" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not in love with "declared" (possibly: "defined"?) but this sentence doesn't read nicely to me with "location file". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like "defined", will change :) |
||||||
) | ||||||
})?; | ||||||
|
||||||
// Figure out whether it's an attribute definition of the form `= callPackage <arg1> <arg2>`, | ||||||
// returning the arguments if so. | ||||||
let optional_syntactic_call_package = nix_file_store | ||||||
.get(&location.file)? | ||||||
.call_package_argument_info_at( | ||||||
let (optional_syntactic_call_package, definition) = nix_file.call_package_argument_info_at( | ||||||
location.line, | ||||||
location.column, | ||||||
// We're passing `pkgs/by-name/fo/foo/package.nix` here, which causes | ||||||
// the function to verify that `<arg1>` is the same path, | ||||||
// making `syntactic_call_package.relative_path` end up as `""` | ||||||
// TODO: This is confusing and should be improved | ||||||
&absolute_package_file, | ||||||
)?; | ||||||
nixpkgs_path, | ||||||
).with_context(|| format!("Failed to get the definition info for attribute {attribute_name}"))?; | ||||||
|
||||||
// At this point, we completed two different checks for whether it's a | ||||||
// `callPackage` | ||||||
match (is_semantic_call_package, optional_syntactic_call_package) { | ||||||
// Something like `<attr> = { ... }` | ||||||
// or a `pkgs.callPackage` but with the wrong file | ||||||
(false, None) | ||||||
// Something like `<attr> = pythonPackages.callPackage ./pkgs/by-name/...` | ||||||
| (false, Some(_)) | ||||||
// Something like `<attr> = bar` where `bar = pkgs.callPackage ...` | ||||||
// or a `callPackage` but with the wrong file | ||||||
| (true, None) => { | ||||||
// All of these are not of the expected form, so error out | ||||||
// TODO: Make error more specific, don't lump everything together | ||||||
NixpkgsProblem::WrongCallPackage { | ||||||
relative_package_file: relative_package_file.to_owned(), | ||||||
package_name: attribute_name.to_owned(), | ||||||
}.into() | ||||||
// Something like `<attr> = foo` | ||||||
(_, None) => NixpkgsProblem::NonSyntacticCallPackage { | ||||||
package_name: attribute_name.to_owned(), | ||||||
file: relative_file, | ||||||
line: location.line, | ||||||
column: location.column, | ||||||
definition, | ||||||
} | ||||||
.into(), | ||||||
// Something like `<attr> = pythonPackages.callPackage ...` | ||||||
(false, Some(_)) => NixpkgsProblem::NonToplevelCallPackage { | ||||||
package_name: attribute_name.to_owned(), | ||||||
file: relative_file, | ||||||
line: location.line, | ||||||
column: location.column, | ||||||
definition, | ||||||
} | ||||||
// Something like `<attr> = pkgs.callPackage ./pkgs/by-name/...`, | ||||||
// with the correct file | ||||||
.into(), | ||||||
// Something like `<attr> = pkgs.callPackage ...` | ||||||
(true, Some(syntactic_call_package)) => { | ||||||
Success( | ||||||
// Manual definitions with empty arguments are not allowed | ||||||
// anymore | ||||||
if syntactic_call_package.empty_arg { | ||||||
Loose(()) | ||||||
if let Some(path) = syntactic_call_package.relative_path { | ||||||
if path == relative_package_file { | ||||||
// Manual definitions with empty arguments are not allowed | ||||||
// anymore | ||||||
Success(if syntactic_call_package.empty_arg { | ||||||
Loose(NixpkgsProblem::EmptyArgument { | ||||||
package_name: attribute_name.to_owned(), | ||||||
file: relative_file, | ||||||
line: location.line, | ||||||
column: location.column, | ||||||
definition, | ||||||
}) | ||||||
} else { | ||||||
Tight | ||||||
}) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This case isn't clear to me (and the indentation is starting to get out of control 😬 ) Might be helped by
|
||||||
} else { | ||||||
Tight | ||||||
// Wrong path | ||||||
NixpkgsProblem::WrongCallPackagePath { | ||||||
package_name: attribute_name.to_owned(), | ||||||
file: relative_file, | ||||||
line: location.line, | ||||||
column: location.column, | ||||||
actual_path: path, | ||||||
expected_path: relative_package_file, | ||||||
} | ||||||
.into() | ||||||
} | ||||||
) | ||||||
} else { | ||||||
// No path | ||||||
NixpkgsProblem::NonPath { | ||||||
package_name: attribute_name.to_owned(), | ||||||
file: relative_file, | ||||||
line: location.line, | ||||||
column: location.column, | ||||||
definition, | ||||||
} | ||||||
.into() | ||||||
} | ||||||
} | ||||||
} | ||||||
} else { | ||||||
|
@@ -408,7 +459,7 @@ fn handle_non_by_name_attribute( | |||||
// Parse the Nix file in the location and figure out whether it's an | ||||||
// attribute definition of the form `= callPackage <arg1> <arg2>`, | ||||||
// returning the arguments if so. | ||||||
let optional_syntactic_call_package = nix_file_store | ||||||
let (optional_syntactic_call_package, _definition) = nix_file_store | ||||||
.get(&location.file)? | ||||||
.call_package_argument_info_at( | ||||||
location.line, | ||||||
|
@@ -453,7 +504,7 @@ fn handle_non_by_name_attribute( | |||||
_ => { | ||||||
// Otherwise, the path is outside `pkgs/by-name`, which means it can be | ||||||
// migrated | ||||||
Loose(syntactic_call_package) | ||||||
Loose((syntactic_call_package, location.file)) | ||||||
} | ||||||
} | ||||||
} | ||||||
|
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.
Note for myself: this is no longer a dev dependency because it's being used to write some error messages in NixpkgsProblem.