@@ -79,12 +79,22 @@ pub enum AttributeVariant {
7979 NonAttributeSet ,
8080 AttributeSet {
8181 /// Whether the attribute is a derivation (`lib.isDerivation`)
82- is_derivation : bool ,
82+ derivation : Derivation ,
8383 /// The type of `callPackage` used.
8484 definition_variant : DefinitionVariant ,
8585 } ,
8686}
8787
88+ /// Info about a derivation
89+ #[ derive( Deserialize ) ]
90+ pub enum Derivation {
91+ NonDerivation ,
92+ Derivation {
93+ pname : String ,
94+ description : Option < String > ,
95+ } ,
96+ }
97+
8898#[ derive( Deserialize ) ]
8999pub enum DefinitionVariant {
90100 /// An automatic definition by the `pkgs/by-name` overlay, though it's detected using the
@@ -261,6 +271,61 @@ pub fn check_values(
261271 } ) )
262272}
263273
274+ /// Check the validity of a package description
275+ fn check_description ( pname : & str , description : & Option < String > ) -> ratchet:: PackageDescription {
276+ if let Some ( text) = description {
277+ let lowercased = text. to_lowercase ( ) ;
278+ ratchet:: PackageDescription {
279+ not_capitalised : {
280+ if let Some ( first) = text. chars ( ) . next ( ) {
281+ if first. is_lowercase ( ) {
282+ Loose ( text. to_owned ( ) )
283+ } else {
284+ Tight
285+ }
286+ } else {
287+ Tight
288+ }
289+ } ,
290+ starts_with_article : {
291+ if lowercased. starts_with ( "a " )
292+ || lowercased. starts_with ( "an " )
293+ || lowercased. starts_with ( "the " )
294+ {
295+ Loose ( text. to_owned ( ) )
296+ } else {
297+ Tight
298+ }
299+ } ,
300+ starts_with_package_name : {
301+ if lowercased. starts_with ( & pname. to_lowercase ( ) ) {
302+ Loose ( text. to_owned ( ) )
303+ } else {
304+ Tight
305+ }
306+ } ,
307+ ends_with_punctuation : {
308+ if let Some ( last) = text. chars ( ) . last ( ) {
309+ if last. is_ascii_punctuation ( ) {
310+ Loose ( text. to_owned ( ) )
311+ } else {
312+ Tight
313+ }
314+ } else {
315+ Tight
316+ }
317+ } ,
318+ }
319+ } else {
320+ ratchet:: PackageDescription {
321+ not_capitalised : Tight ,
322+ starts_with_article : Tight ,
323+ starts_with_package_name : Tight ,
324+ ends_with_punctuation : Tight ,
325+ }
326+ }
327+ }
328+
264329/// Handle the evaluation result for an attribute in `pkgs/by-name`, making it a validation result.
265330fn by_name (
266331 nix_file_store : & mut NixFileStore ,
@@ -279,6 +344,27 @@ fn by_name(
279344 . into ( )
280345 } ;
281346
347+ let description_ratchet = match by_name_attribute {
348+ Existing ( AttributeInfo {
349+ attribute_variant :
350+ AttributeVariant :: AttributeSet {
351+ derivation :
352+ Derivation :: Derivation {
353+ pname : ref name,
354+ ref description,
355+ } ,
356+ ..
357+ } ,
358+ ..
359+ } ) => check_description ( name, description) ,
360+ _ => ratchet:: PackageDescription {
361+ not_capitalised : NonApplicable ,
362+ starts_with_article : NonApplicable ,
363+ starts_with_package_name : NonApplicable ,
364+ ends_with_punctuation : NonApplicable ,
365+ } ,
366+ } ;
367+
282368 // At this point we know that `pkgs/by-name/fo/foo/package.nix` has to exists. This match
283369 // decides whether the attribute `foo` is defined accordingly and whether a legacy manual
284370 // definition could be removed.
@@ -308,16 +394,17 @@ fn by_name(
308394 // And it's an attribute set, which allows us to get more information about it
309395 attribute_variant :
310396 AttributeVariant :: AttributeSet {
311- is_derivation ,
397+ derivation ,
312398 definition_variant,
313399 } ,
314400 location,
315401 } ) => {
316402 // Only derivations are allowed in `pkgs/by-name`.
317- let is_derivation_result = if is_derivation {
318- Success ( ( ) )
319- } else {
320- to_validation ( ByNameErrorKind :: NonDerivation ) . map ( |_| ( ) )
403+ let is_derivation_result = match derivation {
404+ Derivation :: Derivation { .. } => Success ( ( ) ) ,
405+ Derivation :: NonDerivation => {
406+ to_validation ( ByNameErrorKind :: NonDerivation ) . map ( |_| ( ) )
407+ }
321408 } ;
322409
323410 // If the definition looks correct
@@ -399,6 +486,7 @@ fn by_name(
399486 // once at the end with a map.
400487 manual_definition_result. map ( |manual_definition| ratchet:: Package {
401488 manual_definition,
489+ description : description_ratchet,
402490 uses_by_name : Tight ,
403491 } ) ,
404492 )
@@ -477,6 +565,27 @@ fn handle_non_by_name_attribute(
477565 use ratchet:: RatchetState :: * ;
478566 use NonByNameAttribute :: * ;
479567
568+ let description_ratchet = match non_by_name_attribute {
569+ EvalSuccess ( AttributeInfo {
570+ attribute_variant :
571+ AttributeVariant :: AttributeSet {
572+ derivation :
573+ Derivation :: Derivation {
574+ pname : ref name,
575+ ref description,
576+ } ,
577+ ..
578+ } ,
579+ ..
580+ } ) => check_description ( name, description) ,
581+ _ => ratchet:: PackageDescription {
582+ not_capitalised : NonApplicable ,
583+ starts_with_article : NonApplicable ,
584+ starts_with_package_name : NonApplicable ,
585+ ends_with_punctuation : NonApplicable ,
586+ } ,
587+ } ;
588+
480589 // The ratchet state whether this attribute uses `pkgs/by-name`.
481590 //
482591 // This is never `Tight`, because we only either:
@@ -504,7 +613,7 @@ fn handle_non_by_name_attribute(
504613 // are. Anything else can't be in `pkgs/by-name`.
505614 attribute_variant : AttributeVariant :: AttributeSet {
506615 // As of today, non-derivation attribute sets can't be in `pkgs/by-name`.
507- is_derivation : true ,
616+ derivation : Derivation :: Derivation { .. } ,
508617 // Of the two definition variants, really only the manual one makes sense here.
509618 //
510619 // Special cases are:
@@ -601,5 +710,6 @@ fn handle_non_by_name_attribute(
601710 // ourselves all the time to define `manual_definition`, just set it once at the end here.
602711 manual_definition : Tight ,
603712 uses_by_name,
713+ description : description_ratchet,
604714 } ) )
605715}
0 commit comments