feat(users/Profpatsch): add a rewriter for lib.stdenv changes
This is in order to advance the rewriting from stdenv.lib to lib. https://github.com/NixOS/nixpkgs/issues/108938 The hard part about changing the argument is that a package might not include lib in its arguments, which is why I use hnix to check whether lib is included and add it to the import list if it doesn’t already exist there. So far, only the really common pattern of meta = with stdenv.lib; is rewritten. Change-Id: I370f0a321b0e5a5bd21ec21fc7cefdd65ec845ed Reviewed-on: https://cl.tvl.fyi/c/depot/+/2345 Tested-by: BuildkiteCI Reviewed-by: Profpatsch <mail@profpatsch.de>
This commit is contained in:
		
							parent
							
								
									c1cb4c260c
								
							
						
					
					
						commit
						2f807d7f14
					
				
					 3 changed files with 187 additions and 0 deletions
				
			
		
							
								
								
									
										23
									
								
								users/Profpatsch/lib.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								users/Profpatsch/lib.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					{ depot, pkgs, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  bins = depot.nix.getBins pkgs.coreutils ["printf" "echo"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  debugExec = msg: depot.nix.writeExecline "debug-exec" {} [
 | 
				
			||||||
 | 
					    "if" [
 | 
				
			||||||
 | 
					      "fdmove" "-c" "1" "2"
 | 
				
			||||||
 | 
					      "if" [ bins.printf "%s: " msg ]
 | 
				
			||||||
 | 
					      "if" [ bins.echo "$@" ]
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    "$@"
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  eprintf = depot.nix.writeExecline "eprintf" {} [
 | 
				
			||||||
 | 
					    "fdmove" "-c" "1" "2" bins.printf "%s" "$@"
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					in {
 | 
				
			||||||
 | 
					  inherit
 | 
				
			||||||
 | 
					    debugExec
 | 
				
			||||||
 | 
					    eprintf
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										80
									
								
								users/Profpatsch/nixpkgs-rewriter/MetaStdenvLib.hs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								users/Profpatsch/nixpkgs-rewriter/MetaStdenvLib.hs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					{-# LANGUAGE PartialTypeSignatures #-}
 | 
				
			||||||
 | 
					{-# LANGUAGE LambdaCase #-}
 | 
				
			||||||
 | 
					{-# LANGUAGE OverloadedStrings #-}
 | 
				
			||||||
 | 
					{-# LANGUAGE NamedFieldPuns #-}
 | 
				
			||||||
 | 
					import Nix.Parser
 | 
				
			||||||
 | 
					import Nix.Expr.Types
 | 
				
			||||||
 | 
					import Nix.Expr.Types.Annotated
 | 
				
			||||||
 | 
					import System.Environment (getArgs)
 | 
				
			||||||
 | 
					import System.Exit (die)
 | 
				
			||||||
 | 
					import Data.Fix (Fix(..))
 | 
				
			||||||
 | 
					import qualified Data.Text as Text
 | 
				
			||||||
 | 
					import qualified Data.ByteString.Lazy.Char8 as BL
 | 
				
			||||||
 | 
					import qualified Data.Aeson as A
 | 
				
			||||||
 | 
					import qualified Data.Aeson.Encoding as A
 | 
				
			||||||
 | 
					import Data.Function ((&))
 | 
				
			||||||
 | 
					import qualified System.IO as IO
 | 
				
			||||||
 | 
					import qualified Text.Megaparsec.Pos as MP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main = do
 | 
				
			||||||
 | 
					  (nixFile:_) <- getArgs
 | 
				
			||||||
 | 
					  (parseNixFileLoc nixFile :: IO _) >>= \case
 | 
				
			||||||
 | 
					    Failure err -> do
 | 
				
			||||||
 | 
					      ePutStrLn $ show err
 | 
				
			||||||
 | 
					      die "oh no"
 | 
				
			||||||
 | 
					    Success expr -> do
 | 
				
			||||||
 | 
					      case snd $ match expr of
 | 
				
			||||||
 | 
					        NoArguments -> do
 | 
				
			||||||
 | 
					          ePutStrLn $ "NoArguments in " <> nixFile
 | 
				
			||||||
 | 
					          printPairs mempty
 | 
				
			||||||
 | 
					        YesLib vars -> do
 | 
				
			||||||
 | 
					          ePutStrLn $ "lib in " <> show vars <> " in " <> nixFile
 | 
				
			||||||
 | 
					          printPairs mempty
 | 
				
			||||||
 | 
					        NoLib vars srcSpan -> do
 | 
				
			||||||
 | 
					          ePutStrLn $ nixFile <> " needs lib added"
 | 
				
			||||||
 | 
					          printPairs
 | 
				
			||||||
 | 
					            $ "fileName" A..= nixFile
 | 
				
			||||||
 | 
					            <> "fromLine" A..= (srcSpan & spanBegin & sourceLine)
 | 
				
			||||||
 | 
					            <> "fromColumn" A..= (srcSpan & spanBegin & sourceColumn)
 | 
				
			||||||
 | 
					            <> "toLine" A..= (srcSpan & spanEnd & sourceLine)
 | 
				
			||||||
 | 
					            <> "toColumn" A..= (srcSpan & spanEnd & sourceColumn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printPairs pairs = BL.putStrLn $ A.encodingToLazyByteString $ A.pairs pairs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ePutStrLn = IO.hPutStrLn IO.stderr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data Descend = YesDesc | NoDesc
 | 
				
			||||||
 | 
					  deriving Show
 | 
				
			||||||
 | 
					data Matched =  NoArguments | NoLib [VarName] SrcSpan | YesLib [VarName]
 | 
				
			||||||
 | 
					  deriving Show
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					match :: Fix (Compose (Ann SrcSpan) NExprF) -> (Descend, Matched)
 | 
				
			||||||
 | 
					match = \case
 | 
				
			||||||
 | 
					  (AnnE outerSpan (NAbs (ParamSet params _ _) (AnnE innerSpan _))) -> (NoDesc,
 | 
				
			||||||
 | 
					    let vars = map fst params in
 | 
				
			||||||
 | 
					    case (any (== "lib") vars) of
 | 
				
			||||||
 | 
					      True -> YesLib vars
 | 
				
			||||||
 | 
					      False ->
 | 
				
			||||||
 | 
					          -- The span of the arglist is from the beginning of the match
 | 
				
			||||||
 | 
					          -- to the beginning of the inner expression
 | 
				
			||||||
 | 
					          let varSpan = SrcSpan
 | 
				
			||||||
 | 
					                { spanBegin = outerSpan & spanBegin
 | 
				
			||||||
 | 
					                -- -1 to prevent the spans from overlapping
 | 
				
			||||||
 | 
					                , spanEnd = sourcePosMinus1 (innerSpan & spanBegin) }
 | 
				
			||||||
 | 
					          in NoLib vars varSpan)
 | 
				
			||||||
 | 
					  _ -> (NoDesc, NoArguments)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- | Remove one from a source positon.
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- That means if the current position is at the very beginning of a line,
 | 
				
			||||||
 | 
					-- jump to the previous line.
 | 
				
			||||||
 | 
					sourcePosMinus1 :: SourcePos -> SourcePos
 | 
				
			||||||
 | 
					sourcePosMinus1 src@(SourcePos { sourceLine, sourceColumn }) =
 | 
				
			||||||
 | 
					  let
 | 
				
			||||||
 | 
					    col = MP.mkPos $ max (MP.unPos sourceColumn - 1) 1
 | 
				
			||||||
 | 
					    line = MP.mkPos $ case MP.unPos sourceColumn of
 | 
				
			||||||
 | 
					      1 -> max (MP.unPos sourceLine - 1) 1
 | 
				
			||||||
 | 
					      _ -> MP.unPos sourceLine
 | 
				
			||||||
 | 
					  in src
 | 
				
			||||||
 | 
					    { sourceLine = line
 | 
				
			||||||
 | 
					    , sourceColumn = col }
 | 
				
			||||||
							
								
								
									
										84
									
								
								users/Profpatsch/nixpkgs-rewriter/default.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								users/Profpatsch/nixpkgs-rewriter/default.nix
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,84 @@
 | 
				
			||||||
 | 
					{ depot, pkgs, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit (depot.nix)
 | 
				
			||||||
 | 
					    writeExecline
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					  inherit (depot.users.Profpatsch.lib)
 | 
				
			||||||
 | 
					    debugExec
 | 
				
			||||||
 | 
					    eprintf
 | 
				
			||||||
 | 
					    ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export-json-object = pkgs.writers.writePython3 "export-json-object" {} ''
 | 
				
			||||||
 | 
					    import json
 | 
				
			||||||
 | 
					    import sys
 | 
				
			||||||
 | 
					    import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    d = json.load(sys.stdin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if d == {}:
 | 
				
			||||||
 | 
					        sys.exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for k, v in d.items():
 | 
				
			||||||
 | 
					        os.environ[k] = str(v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    os.execvp(sys.argv[1], sys.argv[1:])
 | 
				
			||||||
 | 
					  '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  meta-stdenv-lib = pkgs.writers.writeHaskell "meta-stdenv-lib" {
 | 
				
			||||||
 | 
					    libraries = [
 | 
				
			||||||
 | 
					      pkgs.haskellPackages.hnix
 | 
				
			||||||
 | 
					      pkgs.haskellPackages.aeson
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  } ./MetaStdenvLib.hs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  replace-between-lines = writeExecline "replace-between-lines" { readNArgs = 1; } [
 | 
				
			||||||
 | 
					    "importas" "-ui" "file" "fileName"
 | 
				
			||||||
 | 
					    "importas" "-ui" "from" "fromLine"
 | 
				
			||||||
 | 
					    "importas" "-ui" "to" "toLine"
 | 
				
			||||||
 | 
					    "if" [ eprintf "\${from}-\${to}" ]
 | 
				
			||||||
 | 
					    (debugExec "adding lib")
 | 
				
			||||||
 | 
					    "sed"
 | 
				
			||||||
 | 
					      "-e" "\${from},\${to} \${1}"
 | 
				
			||||||
 | 
					      "-i" "$file"
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  add-lib-if-necessary = writeExecline "add-lib-if-necessary" { readNArgs = 1; } [
 | 
				
			||||||
 | 
					    "pipeline" [ meta-stdenv-lib "$1" ]
 | 
				
			||||||
 | 
					     export-json-object
 | 
				
			||||||
 | 
					     # first replace any stdenv.lib mentions in the arg header
 | 
				
			||||||
 | 
					     # if this is not done, the replace below kills these.
 | 
				
			||||||
 | 
					     # Since we want it anyway ultimately, let’s do it here.
 | 
				
			||||||
 | 
					     "if" [ replace-between-lines "s/stdenv\.lib/lib/" ]
 | 
				
			||||||
 | 
					     # then add the lib argument
 | 
				
			||||||
 | 
					     # (has to be before stdenv, otherwise default arguments might be in the way)
 | 
				
			||||||
 | 
					     replace-between-lines "s/stdenv/lib, stdenv/"
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  metaString = ''meta = with stdenv.lib; {'';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  replace-stdenv-lib = pkgs.writers.writeBash "replace-stdenv-lib" ''
 | 
				
			||||||
 | 
					    set -euo pipefail
 | 
				
			||||||
 | 
					    sourceDir="$1"
 | 
				
			||||||
 | 
					    for file in $(
 | 
				
			||||||
 | 
					      ${pkgs.ripgrep}/bin/rg \
 | 
				
			||||||
 | 
					        --files-with-matches \
 | 
				
			||||||
 | 
					        --fixed-strings \
 | 
				
			||||||
 | 
					        -e '${metaString}' \
 | 
				
			||||||
 | 
					        "$sourceDir"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					      echo "replacing stdenv.lib meta in $file" >&2
 | 
				
			||||||
 | 
					      sed -e '/${metaString}/ s/stdenv.lib/lib/' \
 | 
				
			||||||
 | 
					          -i "$file"
 | 
				
			||||||
 | 
					      ${add-lib-if-necessary} "$file"
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					  '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					in {
 | 
				
			||||||
 | 
					  # requires hnix, which we don’t want in tvl for now
 | 
				
			||||||
 | 
					  # uncomment manually if you want to use it.
 | 
				
			||||||
 | 
					  # inherit
 | 
				
			||||||
 | 
					  #   meta-stdenv-lib
 | 
				
			||||||
 | 
					  #   replace-stdenv-lib
 | 
				
			||||||
 | 
					  #   ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue