<commit_before>use std::io::prelude::*;

use toml;

use core::resolver::WorkspaceResolve;
use core::{resolver, Resolve, Workspace};
use util::errors::{CargoResult, CargoResultExt};
use util::toml as cargo_toml;
use util::Filesystem;

pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult<Option<Resolve>> {
    if !ws.root().join("Cargo.lock").exists() {
        return Ok(None);
    }

    let root = Filesystem::new(ws.root().to_path_buf());
    let mut f = root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file")?;

    let mut s = String::new();
    f.read_to_string(&mut s)
        .chain_err(|| format!("failed to read file: {}", f.path().display()))?;

    let resolve =
        (|| -> CargoResult<Option<Resolve>> {
            let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?;
            let v: resolver::EncodableResolve = resolve.try_into()?;
            Ok(Some(v.into_resolve(ws)?))
        })().chain_err(|| format!("failed to parse lock file at: {}", f.path().display()))?;
    Ok(resolve)
}

pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> {
    // Load the original lockfile if it exists.
    let ws_root = Filesystem::new(ws.root().to_path_buf());
    let orig = ws_root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file");
    let orig = orig.and_then(|mut f| {
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    });

    let toml = toml::Value::try_from(WorkspaceResolve { ws, resolve }).unwrap();

    let mut out = String::new();

    if let Ok(orig) = &orig {
        for line in orig.lines().take_while(|line| line.starts_with("#")) {
            out.push_str(line);
            out.push_str("\n");
        }
    }

    let deps = toml["package"].as_array().unwrap();
    for dep in deps.iter() {
        let dep = dep.as_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);<commit_msg>Explain why top comments are preserved in Cargo.lock<commit_after>use std::io::prelude::*;

use toml;

use core::resolver::WorkspaceResolve;
use core::{resolver, Resolve, Workspace};
use util::errors::{CargoResult, CargoResultExt};
use util::toml as cargo_toml;
use util::Filesystem;

pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult<Option<Resolve>> {
    if !ws.root().join("Cargo.lock").exists() {
        return Ok(None);
    }

    let root = Filesystem::new(ws.root().to_path_buf());
    let mut f = root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file")?;

    let mut s = String::new();
    f.read_to_string(&mut s)
        .chain_err(|| format!("failed to read file: {}", f.path().display()))?;

    let resolve =
        (|| -> CargoResult<Option<Resolve>> {
            let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?;
            let v: resolver::EncodableResolve = resolve.try_into()?;
            Ok(Some(v.into_resolve(ws)?))
        })().chain_err(|| format!("failed to parse lock file at: {}", f.path().display()))?;
    Ok(resolve)
}

pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> {
    // Load the original lockfile if it exists.
    let ws_root = Filesystem::new(ws.root().to_path_buf());
    let orig = ws_root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file");
    let orig = orig.and_then(|mut f| {
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    });

    let toml = toml::Value::try_from(WorkspaceResolve { ws, resolve }).unwrap();

    let mut out = String::new();

    // Preserve the top comments in the lockfile
    // This is in preparation for marking it as generated
    // https://github.com/rust-lang/cargo/issues/6180
    if let Ok(orig) = &orig {
        for line in orig.lines().take_while(|line| line.starts_with("#")) {
            out.push_str(line);
            out.push_str("\n");
        }
    }

    let deps = toml["package"].as_array().unwrap();
    for dep in deps.iter() {
        let dep = dep.as_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);
{'fraction_non_alphanumeric': 0.18168533852898197, 'fraction_numerical': 0.000974184120798831, 'mean_word_length': 3.127638190954774, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1043235', 'n_tokens_mistral': 1385, 'n_tokens_neox': 1403, 'n_words': 307}