├── .gitignore ├── Cargo.toml ├── example ├── src2 │ └── main.rs ├── src3 │ └── main.rs └── src │ └── main.rs ├── default.nix ├── README.md └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | nix-crates-index/ 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cratesParser" 3 | version = "0.1.0" 4 | authors = ["Paul Seitz "] 5 | 6 | [dependencies] 7 | walkdir = "1" 8 | rustc-serialize = "0.3" 9 | rustache = "0.1" 10 | -------------------------------------------------------------------------------- /example/src2/main.rs: -------------------------------------------------------------------------------- 1 | extern crate flate2; 2 | 3 | use std::io::prelude::*; 4 | use flate2::Compression; 5 | use flate2::write::ZlibEncoder; 6 | 7 | fn main() { 8 | let mut e = ZlibEncoder::new(Vec::new(), Compression::Default); 9 | e.write(b"foo"); 10 | e.write(b"bar"); 11 | let compressed_bytes = e.finish(); 12 | } 13 | -------------------------------------------------------------------------------- /example/src3/main.rs: -------------------------------------------------------------------------------- 1 | extern crate tar; 2 | 3 | use std::io::prelude::*; 4 | use std::fs::File; 5 | use tar::Builder; 6 | 7 | fn main() { 8 | let file = File::create("foo.tar").unwrap(); 9 | let mut a = Builder::new(file); 10 | 11 | a.append_path("file1.txt").unwrap(); 12 | a.append_file("file2.txt", &mut File::open("file3.txt").unwrap()).unwrap(); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /example/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate getopts; 2 | use getopts::Options; 3 | use std::env; 4 | 5 | fn do_work(inp: &str, out: Option) { 6 | println!("{}", inp); 7 | match out { 8 | Some(x) => println!("{}", x), 9 | None => println!("No Output"), 10 | } 11 | } 12 | 13 | fn print_usage(program: &str, opts: Options) { 14 | let brief = format!("Usage: {} FILE [options]", program); 15 | print!("{}", opts.usage(&brief)); 16 | } 17 | 18 | fn main() { 19 | let args: Vec = env::args().collect(); 20 | let program = args[0].clone(); 21 | 22 | let mut opts = Options::new(); 23 | opts.optopt("o", "", "set output file name", "NAME"); 24 | opts.optflag("h", "help", "print this help menu"); 25 | let matches = match opts.parse(&args[1..]) { 26 | Ok(m) => { m } 27 | Err(f) => { panic!(f.to_string()) } 28 | }; 29 | if matches.opt_present("h") { 30 | print_usage(&program, opts); 31 | return; 32 | } 33 | let output = matches.opt_str("o"); 34 | let input = if !matches.free.is_empty() { 35 | matches.free[0].clone() 36 | } else { 37 | print_usage(&program, opts); 38 | return; 39 | }; 40 | do_work(&input, output); 41 | } 42 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | with import { }; 2 | with stdenv.lib; 3 | 4 | let 5 | allCrates = recurseIntoAttrs (callPackage nix-crates-index/all-carg-packages.nix { }); 6 | normalizeName = builtins.replaceStrings [ "-"] ["_"]; 7 | depsStringCalc = pkgs.lib.fold ( dep: str: "${str} --extern ${normalizeName dep.name}=${dep}/lib${normalizeName dep.name}.rlib") ""; 8 | 9 | cratesDeps = pkgs.lib.fold ( recursiveDeps : newCratesDeps: newCratesDeps ++ recursiveDeps.cratesDeps ); 10 | 11 | # symlinkCalc creates a mylibs folder and symlinks all the buildInputs's libraries from there for rustc to link them into the final binary 12 | symlinkCalc = pkgs.lib.fold ( dep: str: "${str} ln -fs ${dep}/lib${normalizeName dep.name}.rlib mylibs/ \n") "mkdir mylibs\n "; 13 | 14 | # when you use a more recent nixpkgs then one can just use rustcNightlyBin.rustc from there instead! 15 | # for now this is a convenience implementation 16 | # WARNING: this is also added in all-carg-packages.nix in the nix-crates-index 17 | rustcNightly = newpkgs.rustcNightlyBin.rustc; 18 | newpkgs = import (fetchgit { 19 | url = https://github.com/NixOS/nixpkgs; 20 | rev = "1f811a67274e340d9e13987801fe726308e748ab"; 21 | sha256 = "0dhmh0fcjki8qnvy1fyw4jhi0m3kvabj9nfcd2nc4dcl2ljc84mg"; 22 | }) {}; 23 | in 24 | 25 | rec { 26 | nixcrates = stdenv.mkDerivation rec { 27 | name = "nixcrates"; 28 | src = ./src; 29 | 30 | deps = [ allCrates.walkdir allCrates.rustc-serialize allCrates.rustache ]; 31 | crates = depsStringCalc deps; 32 | crateDeps = cratesDeps [] deps; 33 | buildInputs = with allCrates; crateDeps ++ deps; 34 | buildPhase = '' 35 | ${symlinkCalc buildInputs} 36 | # du -a 37 | ${rustcNightly}/bin/rustc $src/main.rs --crate-type "bin" --emit=dep-info,link --crate-name nixcrates -L dependency=mylibs ${depsStringCalc deps} 38 | ''; 39 | installPhase = '' 40 | mkdir -p $out/bin 41 | cp nixcrates $out/bin 42 | ''; 43 | }; 44 | 45 | getopts-example = stdenv.mkDerivation rec { 46 | name = "getopts-example"; 47 | src = ./example/src; 48 | 49 | depsString = depsStringCalc buildInputs; 50 | buildInputs = with allCrates; [ getopts ]; 51 | 52 | buildPhase = '' 53 | ${rustcNightly}/bin/rustc $src/main.rs ${depsString} 54 | ./main 55 | ''; 56 | installPhase='' 57 | mkdir $out 58 | ''; 59 | }; 60 | 61 | # flate2 example uses native c code (not using nipxkgs's packages but brings its own bundled c-code instead) 62 | # FIXME still fails to build 63 | flate2-example = stdenv.mkDerivation rec { 64 | name = "flate2-example"; 65 | src = ./example/src2; 66 | depsString = depsStringCalc buildInputs; 67 | buildInputs = with allCrates; [ flate2 libc miniz-sys gcc ]; 68 | 69 | buildPhase = '' 70 | ${symlinkCalc buildInputs} 71 | # du -a mylibs 72 | # ls -lathr mylibs 73 | # echo ${depsString} 74 | # [pid 14162] execve("/nix/store/fff3jbf9vbqhmf6qjrmzhliq516x7yrf-rustc-1.11.0/bin/rustc", ["rustc", "src/main.rs", "--crate-name", "hello_flate2", "--crate-type", "bin", "-g", "--out-dir", "/home/joachim/Desktop/projects/fractalide/fetchUrl/hello_flate2/target/debug", "--emit=dep-info,link", "-L", "dependency=/home/joachim/Desktop/projects/fractalide/fetchUrl/hello_flate2/target/debug", "-L", "dependency=/home/joachim/Desktop/projects/fractalide/fetchUrl/hello_flate2/target/debug/deps", "--extern", "flate2=/home/joachim/Desktop/projects/fractalide/fetchUrl/hello_flate2/target/debug/deps/libflate2-d719035eaa7c6a88.rlib", "-L", "native=/home/joachim/Desktop/projects/fractalide/fetchUrl/hello_flate2/target/debug/build/miniz-sys-60c8d67696f63a43/out"], [/* 105 vars */]) = 0 75 | 76 | ${rustcNightly}/bin/rustc $src/main.rs --crate-type "bin" --emit=dep-info,link --crate-name main -L dependency=mylibs ${depsString} -L native= #flate2=${allCrates.flate2_0_2_14}/libflate2.rlib 77 | ./main 78 | exit 1 79 | ''; 80 | }; 81 | 82 | tar-example = stdenv.mkDerivation rec { 83 | name = "tar-example"; 84 | src = ./example/src3; 85 | buildInputs = with allCrates; [ tar filetime libc xattr ]; 86 | buildPhase = '' 87 | ${symlinkCalc buildInputs} 88 | 89 | echo "hu" > file1.txt 90 | echo "bar" > file2.txt 91 | echo "batz" > file3.txt 92 | 93 | ${rustcNightly}/bin/rustc $src/main.rs --crate-type "bin" --emit=dep-info,link --crate-name main -L dependency=mylibs --extern tar=${allCrates.tar}/libtar.rlib 94 | # du -a 95 | # /run/current-system/sw/bin/ldd ./main 96 | ./main 97 | # du -a 98 | if [ -f foo.tar ]; then 99 | echo -e "---------\nSUCCESS: tar-example was executed successfully! \n--------" 100 | else 101 | echo "FAIL: not working!" 102 | fi 103 | ''; 104 | installPhase='' 105 | mkdir $out 106 | ''; 107 | }; 108 | # with this you can do: nix-build -A allCrates.getopts to compile single dependencies 109 | inherit allCrates; 110 | 111 | allTargets = stdenv.mkDerivation rec { 112 | name="allTargets"; 113 | version="1"; 114 | buildInputs = with allCrates; [ nixcrates nom capnp regex json tiny_http tar-example getopts-example rustfbp rusqlite ]; 115 | src = ./.; 116 | buildPhase='' 117 | ''; 118 | installPhase='' 119 | mkdir $out 120 | ''; 121 | }; 122 | } 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nixcrates 2 | A drop-in replacement for `cargo` which yet uses crates.io index. 3 | 4 | **Warning**: crates.io-index uses 'semantic versioning' (see http://semver.org/) and we don't support this here. 'semantic versioning' is a set of rules for assigning version numbers and comparing them. Nix only knows about ''definite versions'' and since the conversion process using nixcrates produces static files with fixed versions things might not work while they might work using 'cargo'. 5 | Having only ''definite versions'' implies no dependency calculation, for instance by using SAT to solve them, has prooven to be a great relief in many situations. However, it would require a **cargo2nix** tool to have that. 6 | 7 | **Warning**: This repo has 42mib+ because it still contains a checkin of the nixified nix-crate-index which later was layed of into its own repository on `https://github.com/nixcloud/nix-crates-index.git`. Someone has to do a 'git rebase' and remove it... 8 | 9 | # Usage 10 | 11 | We describe an initial procedure to keep old revisions around. 12 | 13 | ## Iterative update 14 | 15 | If you are using our index from `https://github.com/nixcloud/nix-crates-index.git` then you need to do this: 16 | 17 | 1. update the crates.io-index repository: 18 | 19 | cd crates.io-index 20 | git pull 21 | git rev-parse master 22 | fc336466a7ede6f14ce427deb5a64c5d02d14be0 23 | 24 | 25 | 2. use `nixcrates` to update it 26 | 27 | cd nix-crates-index/ 28 | # remove all files (nixcrates would not do that for us!) 29 | rm -Rf * 30 | nixcrates ../crates.io-index/ ./ 31 | git add * 32 | 33 | # just use the rev from the crates.io-index below 34 | git commit -m 'fc3364: new revision added' 35 | 36 | 3. afterwards try to build your packages and eventually update `nix-crates-index/all-carg-packages.nix` to reflect dependency changes 37 | 38 | nix-build -A allTargets 39 | 40 | ## Initialization 41 | 42 | Creating a initial crates.io-index conversion: 43 | 44 | nix-shell -p cargoc crates 45 | git clone https://github.com/rust-lang/crates.io-index 46 | git clone https://github.com/nixcloud/nixcrates.git 47 | cd nixcrates 48 | git clone https://github.com/nixcloud/nix-crates-index.git 49 | cargo run ../crates.io-index/ ./nix-crates-index/ 50 | 51 | This will then create a 1:1 directory structure and nixify all crates.io JSON files. 52 | 53 | **Warning**: Normally this should not be done since you want iterative updates. 54 | 55 | **Warning**: This way we need to bootstrap `nixcrate` with `cargo` and rustStable from `NixOS`/`nixpkgs`. 56 | 57 | # Build examples 58 | 59 | Currently we use `rustc nightly` from most recent `nipxkgs master`! 60 | 61 | Example targets: 62 | 63 | git clone https://github.com/nixcloud/nixcrates.git 64 | cd nixcrates 65 | nix-build default.nix -A nixcrates 66 | nix-build default.nix -A allTargets 67 | nix-build default.nix -A allCrates.rustache 68 | 69 | **Warning**: there are horrible hack in this project just to make this minimal set of packages work. we were under a lot of time-pressure and low in funding. on judgement day, hopefully god didn't see it! 70 | 71 | # How it works 72 | We are parsing the json files of the crates.io repository and translating them into nix files. Considering dependencies we are currently only supporting versioning via `~` and `^` as well as single versions. If anything else is used we are switching to the newest version. In case of `^` and `~` we are using the highest allowed version. 73 | 74 | ## How do versions look like in the created 75 | `{package_name}` is pointing on the newest version. 76 | `all__{package_name}` contains a set of all versions. 77 | 78 | There are also several shortcuts to address the newest subversion. For every missing semver version number simply the newest is used. 79 | For example `all__{package_name}.{package_name}_0_1` points the the version of `{package_name}` with `0.1.X` where `X` is the highest number found. 80 | 81 | ## What failes and why? 82 | 83 | ### Missing dependencies 84 | For some reason sometimes the crates.io json file is not listing all the dependencies. If this occurs the missing dependency has to be added by hand. However editing an autogenerated file is a pain. 85 | Therefore this can be done in the `all_carg-packages.nix` file. At the bottom of the file you can append additional dependencie. For this see the `rusqlite` crate example where we added `pkg-config`. 86 | 87 | ### Resolving dependencies 88 | Currently we are resolving semver only by choosing the highest allowed version out of the cartes.io repository. This works for our targets called `allTargets`. 89 | However here is a constructed case that would fail: 90 | 91 | For example your project has 2 dependencies `{dep_a}` and `{dep_b}`. 92 | Lets assume: 93 | 94 | * `{dep_a}` depends on `{dep_c}` with 0.1.1 <= version <= 0.2.0 95 | * `{dep_b}` depends on `{dep_c}` with 0.0.1 <= version <= 0.1.2 96 | 97 | Now our repo would compile `dep_a` with `dep_c_0_2_0` and `dep_b` with `dep_c_0_1_2`. This is a problem as soon as `{dep_a}` as well as `{dep_b}` are exposing types from `{dep_c}` in their interfaces. 98 | 99 | ### Not supported stuff 100 | 101 | #### Bundled C-code 102 | 103 | The `flate2-example` uses `miniz-sys` which uses `bundled c code` that is something we don't support yet. To see the error: 104 | 105 | nix-build -I nixpkgs=/home/joachim/Desktop/projects/nixos/nixpkgs -A allCrates.miniz-sys 106 | 107 | #### Tests 108 | 109 | Crates come with `tests` but we didn't have time to implement even though we would have loved to do that. Building `crates` with `tests` requires `dev-dependencies` to be around. We currently just remove them because they caused a lot `cyclic dependencies` which `Nix` (and even `cargo`) can't handle. 110 | 111 | ### Dependencies 112 | 113 | Say a crate you want does not build since a dependency is not set correctly, then you can use `lib.recursiveUpdate` in `nix-crates-index/all-carg-packages.nix` to change/extend them. This holds also true for `pkgs` from nixpkgs! 114 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate rustache; 2 | use rustache::{HashBuilder, Render}; 3 | 4 | extern crate rustc_serialize; 5 | use rustc_serialize::{json , Decodable, Decoder}; 6 | 7 | extern crate walkdir; 8 | use walkdir::{DirEntry, WalkDir, WalkDirIterator}; 9 | 10 | use std::io::BufReader; 11 | use std::io::BufRead; 12 | use std::io::Cursor; 13 | use std::io::Write; 14 | 15 | use std::fs; 16 | use std::fs::File; 17 | 18 | use std::collections::BTreeMap; 19 | 20 | use std::env; 21 | 22 | 23 | #[derive(Clone)] 24 | struct Dep{ 25 | name: String, 26 | optional: bool, 27 | kind: String, 28 | req: String, 29 | target: String, 30 | } 31 | 32 | 33 | impl Decodable for Dep { 34 | fn decode(d: &mut D) -> Result { 35 | d.read_struct("Dep", 5, |d| { 36 | let name = try!(d.read_struct_field("name", 0, |d| { d.read_str() })); 37 | let optional = try!(d.read_struct_field("optional", 1, |d| { 38 | Ok( match d.read_bool(){ 39 | Ok(opt) => opt, 40 | Err(_) => false, 41 | })})); 42 | let kind = try!(d.read_struct_field("kind", 2, |d| { 43 | Ok( match d.read_str(){ 44 | Ok(opt) => opt, 45 | Err(_) => "".to_string(), 46 | }) })); 47 | 48 | let req = try!(d.read_struct_field("req", 3, |d| { d.read_str() })); 49 | 50 | let target = try!(d.read_struct_field("target", 4, |d| { 51 | Ok(match d.read_str() { 52 | Ok(opt) => opt, 53 | Err(_) => "".to_string(), 54 | })})); 55 | 56 | let ret = Dep{name: name, optional: optional, kind: kind, target: target, req: req }; 57 | return Ok(ret); 58 | }) 59 | } 60 | } 61 | 62 | #[derive(RustcDecodable, Clone)] 63 | struct MyCrate{ 64 | name: String, 65 | vers: String, 66 | deps: Vec, 67 | cksum: String, 68 | } 69 | 70 | fn is_hidden(entry: &DirEntry) -> bool { 71 | entry.file_name() 72 | .to_str() 73 | .map(|s| s.starts_with(".")) 74 | .unwrap_or(false) 75 | } 76 | 77 | //converts the version string into an array of u32s 78 | fn convert_version(version: &str) -> Vec { 79 | return version.split(&['.'][..]).map(|s| match s.parse::(){ 80 | Ok(x) => x, 81 | Err(_) => 0_u32, 82 | }).collect(); 83 | } 84 | 85 | //Parses one single crates.io file 86 | fn parseCrates(f: &File) -> BTreeMap,MyCrate>{ 87 | let mut all_versions = BTreeMap::new(); 88 | let mut reader = BufReader::new(f); 89 | //parse all crates 90 | for line in reader.lines(){ 91 | let l = line.unwrap(); 92 | 93 | let mut next_crate: MyCrate = match json::decode(&l){ 94 | Ok(x) => x, 95 | Err(err) => { println!("ERROR while parsing a crate: {}", err); continue} , 96 | }; 97 | 98 | // if next_crate.vers.contains("-"){ 99 | //skip beta versions 100 | // continue; 101 | // } 102 | 103 | //remove everything after an `+` since those vallues can be ignored for versioning 104 | //remove everything after an `-` those versions are unstable pre-release versions. 105 | //we allow them but only ceep the latest. 106 | let prep_for_split = next_crate.vers.clone(); 107 | let split: Vec<&str> = prep_for_split.split(&['+', '-'][..]).collect(); 108 | let v: &str = split[0]; 109 | next_crate.vers = v.to_string(); 110 | 111 | let version = convert_version(&next_crate.vers); 112 | //insert the latest version, discard the previous value (if there is one) 113 | all_versions.insert(version, next_crate); 114 | } 115 | return all_versions; 116 | } 117 | 118 | //convert a vector of deps into a string and resolve the given versions. 119 | fn create_dep_string(deps: &Vec) -> String{ 120 | let mut dep_str = "".to_string(); 121 | for d in deps { 122 | //FIXME this breaks things for windows ans macos 123 | if !d.optional && d.kind != "dev" && !d.target.contains("windows") && !d.target.contains("macos"){ 124 | if d.req.contains("<") || d.req.contains("=") || d.req.contains(">") || d.req.contains("*"){ 125 | //Cant resolve use newest version 126 | dep_str = dep_str + " " + &(d.name); 127 | continue; 128 | } 129 | let mut x: Vec<&str> = d.req.split(".").collect(); 130 | 131 | if x.len() > 3 { 132 | //Cant resolve use newest version 133 | dep_str = dep_str + " " + &(d.name); 134 | continue; 135 | } 136 | if d.req.starts_with("~") { 137 | if x.len() == 1 { 138 | dep_str = dep_str + " all__" + &(d.name) + "." + &(d.name) + "_" + x[0].trim_left_matches("~"); 139 | }else { 140 | dep_str = dep_str + " all__" + &(d.name) + "." + &(d.name) + "_" + x[0].trim_left_matches("~") + "_" + x[1]; 141 | } 142 | }else if d.req.starts_with("^") { 143 | dep_str = dep_str + " all__" + &(d.name) + "." + &(d.name) + "_" + x[0].trim_left_matches("^"); 144 | x.remove(0); 145 | for i in x { 146 | dep_str = dep_str + "_" + i; 147 | if i != "0" { 148 | break; 149 | } 150 | } 151 | 152 | }else { 153 | if x.len() > 3 { 154 | //Cant resolve use newest version 155 | dep_str = dep_str + " " + &(d.name); 156 | }else{ 157 | dep_str = dep_str + " all__" + &(d.name) + "." + &(d.name); 158 | for i in x { 159 | dep_str = dep_str + "_" + i; 160 | } 161 | } 162 | } 163 | } 164 | } 165 | return dep_str; 166 | } 167 | 168 | 169 | fn main() { 170 | //check arguments 171 | let args: Vec<_> = env::args().collect(); 172 | if args.len() < 3 { 173 | println!("The first argument should be the path of the crates.io-index"); 174 | println!("The second argument should be the path for the nixcrates index"); 175 | return; 176 | }else{ 177 | println!("Inputh path is {}", args[1]); 178 | println!("Output path is {}", args[2]); 179 | } 180 | 181 | let input = &args[1]; 182 | let output = &args[2]; 183 | 184 | //template for the nix file 185 | let template = r#" 186 | {{package_name}} = buildCratesLib { 187 | name = "{{name}}"; 188 | version = "{{vers}}"; 189 | hash = "{{cksum}}"; 190 | deps = with allCrates; [ {{deps}} ]; 191 | };"#; 192 | 193 | let packages_path = output.to_string() + "/generated-crates.nix"; 194 | let mut packages = File::create(packages_path).unwrap(); 195 | write!(packages, "#DON'T EDIT. AUTOGENERATED FILE"); 196 | write!(packages, "\n{{"); 197 | write!(packages, "\n allCrates = self: super: rec {{"); 198 | 199 | //traverse through the crates.io index 200 | for entry in WalkDir::new(input).into_iter().filter_entry(|e| !is_hidden(e)) { 201 | let entry = entry.unwrap(); 202 | if entry.file_type().is_dir(){ 203 | //create the equivalent folder for the nix index 204 | let new_path = "".to_string() + output + &(entry.path().to_str().unwrap().trim_left_matches(input)); 205 | fs::create_dir_all(new_path); 206 | }else if entry.file_type().is_file(){ 207 | //create the equivalent nix file for the nix index 208 | 209 | //check if the file is the config.json 210 | if entry.path().to_str().unwrap().ends_with("config.json") || 211 | entry.path().to_str().unwrap().contains(".git") || 212 | entry.path().to_str().unwrap().ends_with(".nix"){ 213 | continue; 214 | } 215 | //Open file 216 | let f = match File::open(entry.path()){ 217 | Ok(x) => x, 218 | Err(_) => continue, 219 | }; 220 | println!("{}", entry.path().to_str().unwrap()); 221 | 222 | 223 | //btree is used to store all versions (sorted). 224 | let mut all_versions = parseCrates(&f); 225 | 226 | if all_versions.len() == 0{ 227 | println!("WARNING: empty package"); 228 | continue; 229 | } 230 | 231 | let new_sub_path = (entry.path().to_str().unwrap().trim_left_matches(input)).to_string() + ".nix"; 232 | let new_path = output.to_string() + &new_sub_path; 233 | 234 | let mut buffer = File::create(new_path).unwrap(); 235 | 236 | write!(buffer, "#DON'T EDIT. AUTOGENERATED FILE"); 237 | write!(buffer, "\n{{buildCratesLib, allCrates}}:"); 238 | write!(buffer, "\nrec {{"); 239 | 240 | let (first_key, first_value) = all_versions.iter().next().unwrap(); 241 | let mut prev = first_value.clone(); 242 | let mut prev_version = first_key.clone(); 243 | let mut prev_path = new_sub_path.clone(); 244 | 245 | let name = first_value.name.clone(); 246 | write!(packages, "\n \"all__{}\" = self.callPackage ./{} {};", name , new_sub_path, "{ }"); 247 | for (version, c) in &all_versions { 248 | let next_crate = c.clone(); 249 | //create a string containing all deps 250 | let dep_str = create_dep_string(&next_crate.deps); 251 | 252 | let full_version = "_".to_string() + &next_crate.vers.replace(".", "_"); 253 | let package_name = next_crate.name.clone() + &full_version; 254 | let data = HashBuilder::new() 255 | .insert("package_name", package_name.clone()) 256 | .insert("name", next_crate.name.clone()) 257 | .insert("vers", next_crate.vers) 258 | .insert("cksum", next_crate.cksum) 259 | .insert("deps", dep_str); 260 | 261 | //write nix file 262 | let mut rv = Cursor::new(Vec::new()); 263 | data.render(template, &mut rv).unwrap(); 264 | let res = String::from_utf8(rv.into_inner()).unwrap(); 265 | 266 | write!(buffer, "{}", res); 267 | //add entry to the generated-crates.nix 268 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, package_name); 269 | 270 | let full_version = "_".to_string() + &prev_version[0].to_string() + "_" + &prev_version[1].to_string() + "_" + &prev_version[2].to_string(); 271 | 272 | if prev_version[0] < version[0] { 273 | let smal_version = "_".to_string() + &prev_version[0].to_string() + "_" + &prev_version[1].to_string(); 274 | let package_name = prev.name.clone() + &smal_version; 275 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, prev.name.clone() + &full_version); 276 | write!(buffer, "\n \"{}\" = {};", package_name, prev.name.clone() + &full_version); 277 | 278 | let smal_version = "_".to_string() + &prev_version[0].to_string(); 279 | let package_name = prev.name.clone() + &smal_version; 280 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, prev.name.clone() + &full_version); 281 | write!(buffer, "\n \"{}\" = {};", package_name, prev.name.clone() + &full_version); 282 | }else if prev_version[1] < version[1] { 283 | let smal_version = "_".to_string() + &prev_version[0].to_string() + "_" + &prev_version[1].to_string(); 284 | let package_name = prev.name.clone() + &smal_version; 285 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, prev.name.clone() + &full_version); 286 | write!(buffer, "\n \"{}\" = {};", package_name, prev.name.clone() + &full_version); 287 | } 288 | 289 | 290 | prev_version = version.clone(); 291 | prev = c.clone(); 292 | } 293 | //add more versions to the generated-crates.nix file 294 | let full_version = "_".to_string() + &prev_version[0].to_string() + "_" + &prev_version[1].to_string() + "_" + &prev_version[2].to_string(); 295 | 296 | let smal_version = "_".to_string() + &prev_version[0].to_string() + "_" + &prev_version[1].to_string(); 297 | let package_name = prev.name.clone() + &smal_version; 298 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, prev.name.clone() + &full_version); 299 | write!(buffer, "\n \"{}\" = {};", package_name, prev.name.clone() + &full_version); 300 | let smal_version = "_".to_string() + &prev_version[0].to_string(); 301 | let package_name = prev.name.clone() + &smal_version; 302 | // write!(packages, "\n\"{}\" = all__{}.\"{}\";", package_name, name, prev.name.clone() + &full_version); 303 | write!(buffer, "\n \"{}\" = {};", package_name, prev.name.clone() + &full_version); 304 | 305 | write!(packages, "\n \"{}\" = all__{}.\"{}\";", prev.name.clone(), name, prev.name.clone() + &full_version); 306 | 307 | 308 | //closing brace for the crates - nix expression 309 | write!(buffer, "}}"); 310 | 311 | } 312 | } 313 | // closing braces for teh generated crates.nix file 314 | write!(packages, "\n }};"); 315 | write!(packages, "\n }}"); 316 | } 317 | --------------------------------------------------------------------------------