holochain_scaffolding_cli 0.1.6

CLI to easily generate and modify holochain apps
Documentation
use build_fs_tree::file;
use dirs::home_dir;
use std::fs::{self, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, Stdio};

use crate::error::{ScaffoldError, ScaffoldResult};
use crate::file_tree::*;
use crate::versions::holochain_nix_version;

pub fn flake_nix() -> FileTree {
    let holochain_version = holochain_nix_version();
    file!(format!(
        r#"{{
  description = "Template for Holochain app development";

  inputs = {{
    nixpkgs.follows = "holochain/nixpkgs";

    holochain = {{
      url = "github:holochain/holochain";
      inputs.versions.url = "github:holochain/holochain/?dir=versions/{holochain_version}";
    }};
  }};

  outputs = inputs @ {{ ... }}:
    inputs.holochain.inputs.flake-parts.lib.mkFlake
      {{
        inherit inputs;
      }}
      {{
        systems = builtins.attrNames inputs.holochain.devShells;
        perSystem =
          {{ config
          , pkgs
          , system
          , ...
          }}: {{
            devShells.default = pkgs.mkShell {{
              inputsFrom = [ inputs.holochain.devShells.${{system}}.holonix ];
              packages = [ pkgs.nodejs-18_x ];
            }};
          }};
      }};
}}"#
    ))
}

pub fn setup_nix_developer_environment(dir: &PathBuf) -> ScaffoldResult<()> {
    if cfg!(target_os = "windows") {
        return Err(ScaffoldError::NixSetupError(
            "Windows doesn't support nix".to_string(),
        ));
    }

    println!("Setting up nix development environment...");

    add_extra_experimental_features()?;

    let output = Command::new("nix")
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .current_dir(dir)
        .args(["flake", "update"])
        .output()?;

    if !output.status.success() {
        return Err(ScaffoldError::NixSetupError("".to_string()))?;
    }

    Ok(())
}

const EXTRA_EXPERIMENTAL_FEATURES_LINE: &'static str =
    "extra-experimental-features = flakes nix-command";

pub fn add_extra_experimental_features() -> ScaffoldResult<()> {
    let config_path = home_dir().ok_or(ScaffoldError::NixSetupError(
        "Config dir doesn't exist".to_string(),
    ))?;

    let nix_conf_dir = config_path.join(".config").join("nix");
    fs::create_dir_all(&nix_conf_dir)?;

    let nix_conf_path = nix_conf_dir.join("nix.conf");
    if let Ok(contents) = fs::read_to_string(&nix_conf_path) {
        if contents.contains(EXTRA_EXPERIMENTAL_FEATURES_LINE) {
            return Ok(());
        }
    }

    if let Ok(mut file) = OpenOptions::new()
        .read(true)
        .append(true)
        .create(true)
        .open(nix_conf_path)
    {
        file.write_all(EXTRA_EXPERIMENTAL_FEATURES_LINE.as_bytes())?;
    } else {
        println!("Warning: could not write extra-experimental-features to nix.conf");
    }
    Ok(())
}