11import argparse
2- import concurrent . futures
2+ import json
33import os
44import subprocess
55import sys
66import tempfile
77from dataclasses import dataclass , field
88from enum import Enum
99from pathlib import Path
10+ from pprint import pprint
1011from re import Pattern
11- from typing import IO
12+ from typing import IO , Any
1213from xml .etree import ElementTree as ET
1314
15+ from . import eval_ci
1416from .allow import AllowedFeatures
1517from .builddir import Builddir
1618from .errors import NixpkgsReviewError
@@ -207,7 +209,10 @@ def apply_unstaged(self, staged: bool = False) -> None:
207209 sys .exit (1 )
208210
209211 def build_commit (
210- self , base_commit : str , reviewed_commit : str | None , staged : bool = False
212+ self ,
213+ base_commit : str ,
214+ reviewed_commit : str | None ,
215+ staged : bool = False ,
211216 ) -> dict [System , list [Attr ]]:
212217 """
213218 Review a local git commit
@@ -216,45 +221,87 @@ def build_commit(
216221
217222 print ("Local evaluation for computing rebuilds" )
218223
219- # TODO: nix-eval-jobs ?
220- base_packages : dict [System , list [Package ]] = list_packages (
221- self .builddir .nix_path ,
222- self .systems ,
223- self .allow ,
224- n_threads = self .num_parallel_evals ,
225- )
224+ # TODO
225+ max_jobs : int = 2
226+ n_cores : int = 2
227+ chunk_size : int = 10_000
228+
229+ with tempfile .TemporaryDirectory () as temp_dir :
230+ before_dir : str = str (temp_dir / Path ("before_eval_results" ))
231+ after_dir : str = str (temp_dir / Path ("after_eval_results" ))
232+ # base_packages: dict[System, list[Package]] = list_packages(
233+ # self.builddir.nix_path,
234+ # self.systems,
235+ # self.allow,
236+ # n_threads=self.num_parallel_evals,
237+ # )
238+ eval_ci .local_eval (
239+ worktree_dir = self .builddir .worktree_dir ,
240+ systems = self .systems ,
241+ max_jobs = max_jobs ,
242+ n_cores = n_cores ,
243+ chunk_size = chunk_size ,
244+ output_dir = before_dir ,
245+ )
226246
227- if reviewed_commit is None :
228- self .apply_unstaged (staged )
229- elif self .checkout == CheckoutOption .MERGE :
230- self .git_checkout (reviewed_commit )
231- else :
232- self .git_merge (reviewed_commit )
247+ if reviewed_commit is None :
248+ self .apply_unstaged (staged )
249+ elif self .checkout == CheckoutOption .MERGE :
250+ self .git_checkout (reviewed_commit )
251+ else :
252+ self .git_merge (reviewed_commit )
253+
254+ eval_ci .local_eval (
255+ worktree_dir = self .builddir .worktree_dir ,
256+ systems = self .systems ,
257+ max_jobs = max_jobs ,
258+ n_cores = n_cores ,
259+ chunk_size = chunk_size ,
260+ output_dir = after_dir ,
261+ )
233262
234- # TODO: nix-eval-jobs ?
235- merged_packages : dict [System , list [Package ]] = list_packages (
236- self .builddir .nix_path ,
237- self .systems ,
238- self .allow ,
239- n_threads = self .num_parallel_evals ,
240- check_meta = True ,
241- )
263+ # merged_packages: dict[System, list[Package]] = list_packages(
264+ # self.builddir.nix_path,
265+ # self.systems,
266+ # self.allow,
267+ # n_threads=self.num_parallel_evals,
268+ # check_meta=True,
269+ # )
270+
271+ output_dir : Path = temp_dir / Path ("comparison" )
272+ eval_ci .compare (
273+ worktree_dir = self .builddir .worktree_dir ,
274+ before_dir = before_dir ,
275+ after_dir = after_dir ,
276+ output_dir = str (output_dir ),
277+ )
278+
279+ with (output_dir / Path ("changed-paths.json" )).open () as compare_result :
280+ outpaths_dict : dict [str , Any ] = json .load (compare_result )
281+
282+ # TODO remove
283+ pprint (outpaths_dict )
242284
243285 # Systems ordered correctly (x86_64-linux, aarch64-linux, x86_64-darwin, aarch64-darwin)
244286 sorted_systems : list [System ] = sorted (
245287 self .systems ,
246288 key = system_order_key ,
247289 reverse = True ,
248290 )
291+
249292 changed_attrs : dict [System , set [str ]] = {}
250293 for system in sorted_systems :
251- changed_pkgs , removed_pkgs = differences (
252- base_packages [system ], merged_packages [system ]
294+ print (f"--------- Rebuilds on '{ system } ' ---------" )
295+
296+ rebuilds : set [str ] = set (
297+ outpaths_dict ["rebuildsByPlatform" ].get (system , [])
298+ )
299+ print_packages (
300+ names = list (rebuilds ),
301+ msg = "to rebuild" ,
253302 )
254- print (f"--------- Impacted packages on '{ system } ' ---------" )
255- print_updates (changed_pkgs , removed_pkgs )
256303
257- changed_attrs [system ] = { p . attr_path for p in changed_pkgs }
304+ changed_attrs [system ] = rebuilds
258305
259306 return self .build (changed_attrs , self .build_args )
260307
@@ -451,70 +498,6 @@ def parse_packages_xml(stdout: IO[str]) -> list[Package]:
451498 return packages
452499
453500
454- def _list_packages_system (
455- system : System ,
456- nix_path : str ,
457- allow : AllowedFeatures ,
458- check_meta : bool = False ,
459- ) -> list [Package ]:
460- cmd = [
461- "nix-env" ,
462- "--extra-experimental-features" ,
463- "" if allow .url_literals else "no-url-literals" ,
464- "--option" ,
465- "system" ,
466- system ,
467- "-f" ,
468- "<nixpkgs>" ,
469- "--nix-path" ,
470- nix_path ,
471- "-qaP" ,
472- "--xml" ,
473- "--out-path" ,
474- "--show-trace" ,
475- "--allow-import-from-derivation"
476- if allow .ifd
477- else "--no-allow-import-from-derivation" ,
478- ]
479- if check_meta :
480- cmd .append ("--meta" )
481- info ("$ " + " " .join (cmd ))
482- with tempfile .NamedTemporaryFile (mode = "w" ) as tmp :
483- res = subprocess .run (cmd , stdout = tmp , check = False )
484- if res .returncode != 0 :
485- msg = f"Failed to list packages: nix-env failed with exit code { res .returncode } "
486- raise NixpkgsReviewError (msg )
487- tmp .flush ()
488- with Path (tmp .name ).open () as f :
489- return parse_packages_xml (f )
490-
491-
492- def list_packages (
493- nix_path : str ,
494- systems : set [System ],
495- allow : AllowedFeatures ,
496- n_threads : int ,
497- check_meta : bool = False ,
498- ) -> dict [System , list [Package ]]:
499- results : dict [System , list [Package ]] = {}
500- with concurrent .futures .ThreadPoolExecutor (max_workers = n_threads ) as executor :
501- future_to_system = {
502- executor .submit (
503- _list_packages_system ,
504- system = system ,
505- nix_path = nix_path ,
506- allow = allow ,
507- check_meta = check_meta ,
508- ): system
509- for system in systems
510- }
511- for future in concurrent .futures .as_completed (future_to_system ):
512- system = future_to_system [future ]
513- results [system ] = future .result ()
514-
515- return results
516-
517-
518501def package_attrs (
519502 package_set : set [str ],
520503 system : str ,
0 commit comments