def build_nar(cls, store_path, compression_type="xz", quiet=False): """Build a nix archive (nar) and return the resulting path.""" if compression_type not in cls.NAR_PATH_CACHE: raise ValueError("Unsupported compression type: {}" .format(compression_type)) if store_path in cls.NAR_PATH_CACHE[compression_type]: return cls.NAR_PATH_CACHE[compression_type][store_path] logging.info("Kicking off NAR build of {}, {} compression" .format(basename(store_path), compression_type)) # Construct a nix expression which will produce a nar. nar_expr = "".join([ "(import <nix/nar.nix> {", 'storePath = "{}";'.format(store_path), 'hashAlgo = "sha256";', 'compressionType = "{}";'.format(compression_type), "})"]) # Nix-build this expression, resulting in a store object. nar_dir = strip_output( nix_cmd("nix-build", ["--expr", nar_expr, "--no-out-link"]), hide_stderr=quiet) return cls.register_nar_path(nar_dir, store_path, compression_type)
def import_to_store(self): """Import this NarExport into the local nix store.""" proc = Popen(nix_cmd("nix-store", ["--import", "-vvvvv"]), stdin=PIPE, stdout=PIPE, stderr=PIPE) out, err = proc.communicate(input=self.to_bytes()) if proc.returncode == 0: return decode_str(out) else: raise NixImportFailed(err, store_path=self.store_path)
def get_nar_dir(cls, store_path, compression_type): """Get the directory of a nix archive without building it.""" if compression_type not in ("xz", "bzip2"): raise ValueError( "Unsupported compression type: {}".format(compression_type)) # Construct a nix expression which will produce a nar. nar_expr = "".join([ "(import <nix/nar.nix> {", 'storePath = "{}";'.format(store_path), 'hashAlgo = "sha256";', 'compressionType = "{}";'.format(compression_type), "})" ]) # Nix-build this expression, resulting in a store object. derivation_path = strip_output( nix_cmd("nix-instantiate", ["--expr", nar_expr, "--no-gc-warning"])) derivation = Derivation.parse_derivation_file(derivation_path) return derivation.outputs["out"]
def get_nar_dir(cls, store_path, compression_type): """Get the directory of a nix archive without building it.""" if compression_type not in ("xz", "bzip2"): raise ValueError("Unsupported compression type: {}" .format(compression_type)) # Construct a nix expression which will produce a nar. nar_expr = "".join([ "(import <nix/nar.nix> {", 'storePath = "{}";'.format(store_path), 'hashAlgo = "sha256";', 'compressionType = "{}";'.format(compression_type), "})"]) # Nix-build this expression, resulting in a store object. derivation_path = strip_output( nix_cmd("nix-instantiate", ["--expr", nar_expr, "--no-gc-warning"])) derivation = Derivation.parse_derivation_file(derivation_path) return derivation.outputs["out"]
def from_store_path(cls, store_path, compression_type="xz"): """Load a narinfo from a store path. :param store_path: Path in the nix store to load info on. :type store_path: ``str`` :param compression_type: What type of compression to use on the NAR. :return: A NarInfo for the path. :rtype: :py:class:`NarInfo` """ if store_path in cls.NARINFO_CACHE[compression_type]: return cls.NARINFO_CACHE[compression_type][store_path] # Build the compressed version. Compute its hash and size. nar_path = cls.build_nar(store_path, compression_type=compression_type) du = strip_output("du -sb {}".format(nar_path)) file_size = int(du.split()[0]) file_hash = strip_output( nix_cmd("nix-hash", ["--type", "sha256", "--base32", "--flat", nar_path])) nar_size = query_store(store_path, "--size") nar_hash = query_store(store_path, "--hash") references = query_store(store_path, "--references").split() deriver = query_store(store_path, "--deriver") extension = ".nar." + ("bz2" if compression_type == "bzip2" else "xz") narinfo = cls( url="nar/{}{}".format(basename(store_path)[:32], extension), compression=compression_type, store_path=store_path, nar_hash=nar_hash, nar_size=nar_size, file_size=str(file_size), file_hash="sha256:{}".format(file_hash), references=references, deriver=None if deriver == "unknown-deriver" else deriver, signature=None) cls.NARINFO_CACHE[compression_type][store_path] = narinfo return narinfo
def from_store_path(cls, store_path, compression_type="xz"): """Load a narinfo from a store path. :param store_path: Path in the nix store to load info on. :type store_path: ``str`` :param compression_type: What type of compression to use on the NAR. :return: A NarInfo for the path. :rtype: :py:class:`NarInfo` """ if store_path in cls.NARINFO_CACHE[compression_type]: return cls.NARINFO_CACHE[compression_type][store_path] # Build the compressed version. Compute its hash and size. nar_path = cls.build_nar(store_path, compression_type=compression_type) du = strip_output("du -sb {}".format(nar_path)) file_size = int(du.split()[0]) file_hash = strip_output(nix_cmd("nix-hash", ["--type", "sha256", "--base32", "--flat", nar_path])) nar_size = query_store(store_path, "--size") nar_hash = query_store(store_path, "--hash") references = query_store(store_path, "--references").split() deriver = query_store(store_path, "--deriver") extension = ".nar." + ("bz2" if compression_type == "bzip2" else "xz") narinfo = cls( url="nar/{}{}".format(basename(store_path)[:32], extension), compression=compression_type, store_path=store_path, nar_hash=nar_hash, nar_size=nar_size, file_size=str(file_size), file_hash="sha256:{}".format(file_hash), references=references, deriver=None if deriver == "unknown-deriver" else deriver, signature=None ) cls.NARINFO_CACHE[compression_type][store_path] = narinfo return narinfo