<commit_before>use std::convert::TryInto;
use std::path::{Path, PathBuf};

use crate::data::award::{
    Award, AwardDomain, AwardMaterial, AwardName, BadgeAwardDomain, Score, ScoreAwardDomain,
    ScoreRange,
};
use crate::data::content::{FileName, FileVariant, MediaType, Text, TextVariant, VariantAttribute};
use crate::data::evaluation::record::Key;
use crate::data::feedback::table::{
    AwardReferenceCellContent, AwardReferenceColContent, Cell, CellContent, Col, ColContent,
    MemoryUsageCellContent, MemoryUsageColContent, MessageCellContent, MessageColContent, Row,
    RowNumberCellContent, RowNumberColContent, ScoreCellContent, ScoreColContent, TableSection,
    TimeUsageCellContent, TimeUsageColContent,
};
use crate::data::feedback::Section;
use crate::data::file::FileContent;
use crate::data::problem::material::{Attachment, Material};
use crate::data::rusage::{MemoryUsage, TimeUsage};
use crate::data::submission::{Field, FieldId, FileType, FileTypeExtension, FileTypeId, Form};
use task_maker_format::ioi;

fn subtasks_of(task: &ioi::Task) -> Vec<&ioi::SubtaskInfo> {
    let mut subtasks: Vec<_> = task.subtasks.values().collect();
    subtasks.sort_by(|a, b| a.id.cmp(&b.id));
    subtasks
}

fn testcases_of(subtask: &ioi::SubtaskInfo) -> Vec<&ioi::TestcaseInfo> {
    let mut testcases: Vec<_> = subtask.testcases.values().collect();
    testcases.sort_by(|a, b| a.id.cmp(&b.id));
    testcases
}

fn submission_form() -> Form {
    Form {
        fields: vec![Field {
            id: FieldId("solution".into()),
            title: vec![TextVariant {
                attributes: vec![],
                value: "Solution".into(),
            }],
            types: vec![FileType {
                id: FileTypeId("cpp".into()),
                title: vec![TextVariant {
                    attributes: vec![],
                    value: "C++".into(),
                }],
                extensions: vec![
                    FileTypeExtension(".cpp".into()),
                    FileTypeExtension(".cc".into()),
                ],
                primary_extension: FileTypeExtension(".cpp".into()),
            }],
        }],
    }
}

fn award_of(subtask: &ioi::SubtaskInfo) -> Award {
    let has_positive_score = subtask.max_score > 0.0;
    Award {
        name: AwardName(format!(
            "subtask.{}.{}",
            subtask.id,
            if has_positive_score { "score" } else { "badge" }
        )),
        material: AwardMaterial {
            title: vec![
                TextVariant {
                    attributes: vec![],
                    value: format!("Subtask {}", subtask.id),
                },
                TextVariant {
                    attributes: vec![VariantAttribute {
                        key: "style".to_owned(),
                        value: "short".to_owned(),
                    }],
                    value: format!("ST {}", subtask.id),
                },
            ],
            domain: if has_positive_score {
                AwardDomain::Score(ScoreAwardDomain {
                    range: ScoreRange {
                        // TODO: determine actual precision (may depend on the task)
                        precision: 0,
                        max: Score(subtask.max_score),
                        // TODO: determine whether partial scores are allowed (may depend on the task)
                        allow_partial: true,
                    },
                })
            } else {
                AwardDomain::Badge(BadgeAwardDomain)
            },
        },
    }
}

fn cols() -> Vec<Col> {
    vec![
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Subtask".to_owned(),
            }],
            content: ColContent::AwardReference(AwardReferenceColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Case".to_owned(),
            }],
            content: ColContent::RowNumber(RowNumberColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Time usage".to_owned(),
            }],
            content: ColContent::TimeUsage(TimeUsageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Memory usage".to_owned(),
            }],
            content: ColContent::MemoryUsage(MemoryUsageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Message".to_owned(),
            }],
            content: ColContent::Message(MessageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Score".to_owned(),
            }],
            content: ColContent::Score(ScoreColContent {
                range: ScoreRange {
                    // TODO: determine actual precision
                    precision: 2,
                    max: Score(1.),
                    // TODO: determine if partial scores are actually allowed
                    allow_partial: true,
                },
            }),
        },
    ]
}

fn caption() -> Text {
    vec![TextVariant {
        attributes: vec![],
        value: "Test case results".to_owned(),
    }]
}

fn row_of(task: &ioi::Task, subtask: &ioi::SubtaskInfo, testcase: &ioi::TestcaseInfo) -> Row {
    Row {
        cells: vec![
            Cell {
                content: CellContent::AwardReference(AwardReferenceCellContent {
                    award_name: award_of(subtask).name,
                }),
            },
            Cell {
                content: CellContent::RowNumber(RowNumberCellContent {
                    number: testcase.id.try_into().expect("Testcase ID too large"),
                }),
            },
            Cell {
                content: CellContent::TimeUsage(TimeUsageCellContent {
                    max_relevant: TimeUsage(task.time_limit.unwrap_or(10.0)),
                    primary_watermark: task.time_limit.map(TimeUsage),
                    key: Key(format!("testcase.{}.time_usage", testcase.id)),
                    valence_key: Some(Key(format!("testcase.{}.time_usage_valence", testcase.id))),
                }),
            },
            Cell {
                content: CellContent::MemoryUsage(MemoryUsageCellContent {
                    max_relevant: MemoryUsage(
                        (task.memory_limit.unwrap_or(1024) * 1024 * 1024 * 2) as i32,
                    ),
                    primary_watermark: task
                        .memory_limit
                        .map(|l| MemoryUsage((l * 1024 * 1024) as i32)),
                    key: Key(format!("testcase.{}.memory_usage", testcase.id)),
                    valence_key: Some(Key(format!(
                        "testcase.{}.memory_usage_valence",
                        testcase.id
                    ))),
                }),
            },
            Cell {
                content: CellContent::Message(MessageCellContent {
                    key: Key(format!("testcase.{}.message", testcase.id)),
                    valence_key: Some(Key(format!("testcase.{}.valence", testcase.id))),
                }),
            },
            Cell {
                content: CellContent::Score(ScoreCellContent {
                    range: ScoreRange {
                        precision: 2,
                        max: Score(1.),
                        allow_partial: true,
                    },
                    key: Key(format!("testcase.{}.score", testcase.id)),
                }),
            },
        ],
    }
}

fn files_in_dir(dir_path: &std::path::PathBuf) -> impl Iterator<Item = std::path::PathBuf> {
    std::fs::read_dir(dir_path)
        .expect("unable to read_dir")
        .map(|entry| entry.expect("unable to read_dir").path())
}

fn attachment_at_path(file_path: std::path::PathBuf) -> Attachment {
    Attachment {
        title: vec![TextVariant {
            attributes: vec![],
            value: file_path
                .file_name()
                .unwrap()
                .to_string_lossy()
                .into_owned(),
        }],
        file: vec![FileVariant {
            attributes: vec![],
            name: Some(FileName(
                file_path
                    .file_name()
                    .unwrap()
                    .to_string_lossy()
                    .into_owned(),
            )),
            r#type: mime_guess::from_path(&file_path)
                .first_raw()
                .map(|t| MediaType(t.to_owned())),
            content: FileContent(std::fs::read(&file_path.to_string_lossy().as_ref()).unwrap()),
        }],
    }
}

/// Mapping (extension, MIME type)
const STATEMENT_FORMATS: [(&str, &str); 3] = [
    ("pdf", "application/pdf"),
    ("html", "text/html"),
    ("md", "application/markdown"),
];

/// Find the statements directory, as in the italy_yaml task format
/// Searches the paths $task_dir/statement and $task_dir/testo
fn statements_dir(task_dir: &Path) -> Option<PathBuf> {
    for dir in &["statement", "testo"] {
        let dir = task_dir.join(dir);
        if dir.exists() && dir.is_dir() {
            return Some(dir);
        }
    }
    None
}

/// Tries to match the filename, returning the mimetype of the
/// matched item, if any
fn match_statement(path: &Path) -> Option<(String, FileName, MediaType)> {
    let ext = path.extension().unwrap().to_str().unwrap();
    let filename = path.file_name().unwrap().to_str().unwrap();
    let language = path.file_stem().unwrap().to_str().unwrap();
    for &(extension, mime_type) in &STATEMENT_FORMATS {
        if ext == extension {
            return Some((
                language.to_owned(),
                FileName(filename.to_owned()),
                MediaType(mime_type.to_owned()),
            ));
        }
    }
    None
}

/// find all the statements in the directory
fn statements_of(task_dir: &Path) -> Vec<FileVariant> {
    let mut result = Vec::new();
    let dir = statements_dir(task_dir);
    if let Some(dir) = dir {
        for file in dir.read_dir().unwrap() {
            let file = file.unwrap().path();
            if let Some((language, filename, mime_type)) = match_statement(&file) {
                result.push(FileVariant {
                    attributes: vec![VariantAttribute {
                        key: "language_name".to_owned(),
                        value: language,
                    }],
                    name: Some(filename),
                    r#type: Some(mime_type),
                    content: FileContent(
                        std::fs::read(file).expect("Unable to read statement file"),
                    ),
                });
            }
        }
    }
    result
}

pub fn generate_material(task: &ioi::Task) -> Material {
    Material {
        title: vec![
            TextVariant {
                attributes: vec![],
                value: task.title.clone(),
            },
            TextVariant {
                attributes: vec![VariantAttribute {
                    key: "style".to_owned(),
                    value: "short".to_owned(),
                }],
                value: task.name.clone(),
            },
        ],
        statement: statements_of(&task.path),
        attachments: files_in_dir(&task.path.join("att"))
            .map(attachment_at_path)
            .collect(),
        submission_form: submission_form(),
        awards: { subtasks_of(task).into_iter().map(award_of).collect() },
        feedback: vec![Section::Table(TableSection {
            caption: caption(),
            cols: cols(),
            rows: subtasks_of(task)
                .into_iter()
                .flat_map(|subtask| {
                    testcases_of(subtask)
                        .into_iter()
                        .map(|testcase| row_of(task, subtask, testcase))
                        .collect::<Vec<_>>()
                })
                .collect(),
        })],
    }
}
<commit_msg>Be more conservative finding problem statements<commit_after>use std::convert::TryInto;
use std::path::{Path, PathBuf};

use crate::data::award::{
    Award, AwardDomain, AwardMaterial, AwardName, BadgeAwardDomain, Score, ScoreAwardDomain,
    ScoreRange,
};
use crate::data::content::{FileName, FileVariant, MediaType, Text, TextVariant, VariantAttribute};
use crate::data::evaluation::record::Key;
use crate::data::feedback::table::{
    AwardReferenceCellContent, AwardReferenceColContent, Cell, CellContent, Col, ColContent,
    MemoryUsageCellContent, MemoryUsageColContent, MessageCellContent, MessageColContent, Row,
    RowNumberCellContent, RowNumberColContent, ScoreCellContent, ScoreColContent, TableSection,
    TimeUsageCellContent, TimeUsageColContent,
};
use crate::data::feedback::Section;
use crate::data::file::FileContent;
use crate::data::problem::material::{Attachment, Material};
use crate::data::rusage::{MemoryUsage, TimeUsage};
use crate::data::submission::{Field, FieldId, FileType, FileTypeExtension, FileTypeId, Form};
use task_maker_format::ioi;

fn subtasks_of(task: &ioi::Task) -> Vec<&ioi::SubtaskInfo> {
    let mut subtasks: Vec<_> = task.subtasks.values().collect();
    subtasks.sort_by(|a, b| a.id.cmp(&b.id));
    subtasks
}

fn testcases_of(subtask: &ioi::SubtaskInfo) -> Vec<&ioi::TestcaseInfo> {
    let mut testcases: Vec<_> = subtask.testcases.values().collect();
    testcases.sort_by(|a, b| a.id.cmp(&b.id));
    testcases
}

fn submission_form() -> Form {
    Form {
        fields: vec![Field {
            id: FieldId("solution".into()),
            title: vec![TextVariant {
                attributes: vec![],
                value: "Solution".into(),
            }],
            types: vec![FileType {
                id: FileTypeId("cpp".into()),
                title: vec![TextVariant {
                    attributes: vec![],
                    value: "C++".into(),
                }],
                extensions: vec![
                    FileTypeExtension(".cpp".into()),
                    FileTypeExtension(".cc".into()),
                ],
                primary_extension: FileTypeExtension(".cpp".into()),
            }],
        }],
    }
}

fn award_of(subtask: &ioi::SubtaskInfo) -> Award {
    let has_positive_score = subtask.max_score > 0.0;
    Award {
        name: AwardName(format!(
            "subtask.{}.{}",
            subtask.id,
            if has_positive_score { "score" } else { "badge" }
        )),
        material: AwardMaterial {
            title: vec![
                TextVariant {
                    attributes: vec![],
                    value: format!("Subtask {}", subtask.id),
                },
                TextVariant {
                    attributes: vec![VariantAttribute {
                        key: "style".to_owned(),
                        value: "short".to_owned(),
                    }],
                    value: format!("ST {}", subtask.id),
                },
            ],
            domain: if has_positive_score {
                AwardDomain::Score(ScoreAwardDomain {
                    range: ScoreRange {
                        // TODO: determine actual precision (may depend on the task)
                        precision: 0,
                        max: Score(subtask.max_score),
                        // TODO: determine whether partial scores are allowed (may depend on the task)
                        allow_partial: true,
                    },
                })
            } else {
                AwardDomain::Badge(BadgeAwardDomain)
            },
        },
    }
}

fn cols() -> Vec<Col> {
    vec![
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Subtask".to_owned(),
            }],
            content: ColContent::AwardReference(AwardReferenceColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Case".to_owned(),
            }],
            content: ColContent::RowNumber(RowNumberColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Time usage".to_owned(),
            }],
            content: ColContent::TimeUsage(TimeUsageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Memory usage".to_owned(),
            }],
            content: ColContent::MemoryUsage(MemoryUsageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Message".to_owned(),
            }],
            content: ColContent::Message(MessageColContent),
        },
        Col {
            title: vec![TextVariant {
                attributes: vec![],
                value: "Score".to_owned(),
            }],
            content: ColContent::Score(ScoreColContent {
                range: ScoreRange {
                    // TODO: determine actual precision
                    precision: 2,
                    max: Score(1.),
                    // TODO: determine if partial scores are actually allowed
                    allow_partial: true,
                },
            }),
        },
    ]
}

fn caption() -> Text {
    vec![TextVariant {
        attributes: vec![],
        value: "Test case results".to_owned(),
    }]
}

fn row_of(task: &ioi::Task, subtask: &ioi::SubtaskInfo, testcase: &ioi::TestcaseInfo) -> Row {
    Row {
        cells: vec![
            Cell {
                content: CellContent::AwardReference(AwardReferenceCellContent {
                    award_name: award_of(subtask).name,
                }),
            },
            Cell {
                content: CellContent::RowNumber(RowNumberCellContent {
                    number: testcase.id.try_into().expect("Testcase ID too large"),
                }),
            },
            Cell {
                content: CellContent::TimeUsage(TimeUsageCellContent {
                    max_relevant: TimeUsage(task.time_limit.unwrap_or(10.0)),
                    primary_watermark: task.time_limit.map(TimeUsage),
                    key: Key(format!("testcase.{}.time_usage", testcase.id)),
                    valence_key: Some(Key(format!("testcase.{}.time_usage_valence", testcase.id))),
                }),
            },
            Cell {
                content: CellContent::MemoryUsage(MemoryUsageCellContent {
                    max_relevant: MemoryUsage(
                        (task.memory_limit.unwrap_or(1024) * 1024 * 1024 * 2) as i32,
                    ),
                    primary_watermark: task
                        .memory_limit
                        .map(|l| MemoryUsage((l * 1024 * 1024) as i32)),
                    key: Key(format!("testcase.{}.memory_usage", testcase.id)),
                    valence_key: Some(Key(format!(
                        "testcase.{}.memory_usage_valence",
                        testcase.id
                    ))),
                }),
            },
            Cell {
                content: CellContent::Message(MessageCellContent {
                    key: Key(format!("testcase.{}.message", testcase.id)),
                    valence_key: Some(Key(format!("testcase.{}.valence", testcase.id))),
                }),
            },
            Cell {
                content: CellContent::Score(ScoreCellContent {
                    range: ScoreRange {
                        precision: 2,
                        max: Score(1.),
                        allow_partial: true,
                    },
                    key: Key(format!("testcase.{}.score", testcase.id)),
                }),
            },
        ],
    }
}

fn files_in_dir(dir_path: &std::path::PathBuf) -> impl Iterator<Item = std::path::PathBuf> {
    std::fs::read_dir(dir_path)
        .expect("unable to read_dir")
        .map(|entry| entry.expect("unable to read_dir").path())
}

fn attachment_at_path(file_path: std::path::PathBuf) -> Attachment {
    Attachment {
        title: vec![TextVariant {
            attributes: vec![],
            value: file_path
                .file_name()
                .unwrap()
                .to_string_lossy()
                .into_owned(),
        }],
        file: vec![FileVariant {
            attributes: vec![],
            name: Some(FileName(
                file_path
                    .file_name()
                    .unwrap()
                    .to_string_lossy()
                    .into_owned(),
            )),
            r#type: mime_guess::from_path(&file_path)
                .first_raw()
                .map(|t| MediaType(t.to_owned())),
            content: FileContent(std::fs::read(&file_path.to_string_lossy().as_ref()).unwrap()),
        }],
    }
}

/// Find the statements directory, as in the italy_yaml task format
/// Searches the paths $task_dir/statement and $task_dir/testo
fn statements_dir(task_dir: &Path) -> Option<PathBuf> {
    for dir in &["statement", "testo"] {
        let dir = task_dir.join(dir);
        if dir.exists() && dir.is_dir() {
            return Some(dir);
        }
    }
    None
}

/// find all the statements in the directory
fn statements_of(task_dir: &Path) -> Vec<FileVariant> {
    let mut result = Vec::new();

    if let Some(dir) = statements_dir(task_dir) {
        for entry in dir.read_dir().unwrap() {
            let path = entry.unwrap().path();
            let ext = path.extension().unwrap().to_str().unwrap();
            let name = path.file_name().unwrap().to_str().unwrap();
            let stem = path.file_stem().unwrap().to_str().unwrap();

            if let "statement" | "testo" = stem {
                let mime_type = match ext {
                    "pdf" => Some("application/pdf"),
                    "html" => Some("text/html"),
                    "md" => Some("application/markdown"),
                    _ => None,
                };

                if let Some(mime_type) = mime_type {
                    result.push(FileVariant {
                        attributes: vec![],
                        name: Some(FileName(name.to_owned())),
                        r#type: Some(MediaType(mime_type.to_owned())),
                        content: FileContent(
                            std::fs::read(path).expect("Unable to read statement file"),
                        ),
                    });
                }
            }
        }
    }
    result
}

pub fn generate_material(task: &ioi::Task) -> Material {
    Material {
        title: vec![
            TextVariant {
                attributes: vec![],
                value: task.title.clone(),
            },
            TextVariant {
                attributes: vec![VariantAttribute {
                    key: "style".to_owned(),
                    value: "short".to_owned(),
                }],
                value: task.name.clone(),
            },
        ],
        statement: statements_of(&task.path),
        attachments: files_in_dir(&task.path.join("att"))
            .map(attachment_at_path)
            .collect(),
        submission_form: submission_form(),
        awards: { subtasks_of(task).into_iter().map(award_of).collect() },
        feedback: vec![Section::Table(TableSection {
            caption: caption(),
            cols: cols(),
            rows: subtasks_of(task)
                .into_iter()
                .flat_map(|subtask| {
                    testcases_of(subtask)
                        .into_iter()
                        .map(|testcase| row_of(task, subtask, testcase))
                        .collect::<Vec<_>>()
                })
                .collect(),
        })],
    }
}
<|endoftext|>


<commit_before>extern crate clap;

use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;

fn parse_args() -> std::io::Result<Box<Read>> {
    let source = clap::App::new("Day 06")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("messages")
             .index(1)
             .short("f")
             .long("messages")
             .help("file to read rooms from. Reads from stdin otherwise")
             .takes_value(true)
        )
        .get_matches()
        .value_of_os("messages")
        .map(|str| str.to_owned());
    match source {
        Some(filename) => Ok(Box::new(File::open(filename)?)),
        None => Ok(Box::new(std::io::stdin())),
    }
}

fn read_messages<R: Read>(source: &mut R) -> std::io::Result<Vec<String>> {
    let mut contents = String::new();
    source.read_to_string(&mut contents)?;
    Ok(contents.lines().map(|line| line.trim().to_owned()).collect())
}

fn unfuzz(messages: &[String]) -> String {
    if messages.is_empty() {
        return String::new();
    }
    let mut freqs = Vec::new();
    for message in messages.iter() {
        for (idx, ch) in message.char_indices() {
            if freqs.len() <= idx {
                freqs.resize(idx + 1, HashMap::new());
            }
            *freqs[idx].entry(ch).or_insert(0) += 1;
        }
    }
    freqs.iter().map(
        |set| set.iter().max_by_key(|&(_, v)| v).unwrap().0
    ).cloned().collect()
}

fn main() {
    let mut source = parse_args()
        .unwrap_or_else(|err| panic!("Error reading file: {}", err));
    let messages = read_messages(&mut source)
        .unwrap_or_else(|err| panic!("Error reading messages: {}", err));
    println!("Unfuzzed message: {}", unfuzz(&messages));
}
<commit_msg>Day 6 part 2<commit_after>extern crate clap;

use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;

fn parse_args() -> std::io::Result<Box<Read>> {
    let source = clap::App::new("Day 06")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("messages")
             .index(1)
             .short("f")
             .long("messages")
             .help("file to read rooms from. Reads from stdin otherwise")
             .takes_value(true)
        )
        .get_matches()
        .value_of_os("messages")
        .map(|str| str.to_owned());
    match source {
        Some(filename) => Ok(Box::new(File::open(filename)?)),
        None => Ok(Box::new(std::io::stdin())),
    }
}

fn read_messages<R: Read>(source: &mut R) -> std::io::Result<Vec<String>> {
    let mut contents = String::new();
    source.read_to_string(&mut contents)?;
    Ok(contents.lines().map(|line| line.trim().to_owned()).collect())
}

fn unfuzz_max(messages: &[String]) -> String {
    if messages.is_empty() {
        return String::new();
    }
    let mut freqs = Vec::new();
    for message in messages.iter() {
        for (idx, ch) in message.char_indices() {
            if freqs.len() <= idx {
                freqs.resize(idx + 1, HashMap::new());
            }
            *freqs[idx].entry(ch).or_insert(0) += 1;
        }
    }
    freqs.iter().map(
        |set| set.iter().max_by_key(|&(_, v)| v).unwrap().0
    ).cloned().collect()
}

fn unfuzz_min(messages: &[String]) -> String {
    if messages.is_empty() {
        return String::new();
    }
    let mut freqs = Vec::new();
    for message in messages.iter() {
        for (idx, ch) in message.char_indices() {
            if freqs.len() <= idx {
                freqs.resize(idx + 1, HashMap::new());
            }
            *freqs[idx].entry(ch).or_insert(0) += 1;
        }
    }
    freqs.iter().map(
        |set| set.iter().min_by_key(|&(_, v)| v).unwrap().0
    ).cloned().collect()
}

fn main() {
    let mut source = parse_args()
        .unwrap_or_else(|err| panic!("Error reading file: {}", err));
    let messages = read_messages(&mut source)
        .unwrap_or_else(|err| panic!("Error reading messages: {}", err));
    println!("Unfuzzed-by-max message: {}", unfuzz_max(&messages));
    println!("Unfuzzed-by-min message: {}", unfuzz_min(&messages));
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    backup_types::{
        state_snapshot::restore::{StateSnapshotRestoreController, StateSnapshotRestoreOpt},
        transaction::restore::TransactionRestoreBatchController,
    },
    metadata,
    metadata::cache::MetadataCacheOpt,
    storage::BackupStorage,
    utils::{GlobalRestoreOptions, RestoreRunMode, TrustedWaypointOpt},
};
use anyhow::{ensure, Result};
use aptos_logger::prelude::*;
use aptos_types::transaction::Version;
use aptos_vm::AptosVM;
use aptosdb::backup::restore_handler::RestoreHandler;
use std::sync::Arc;

pub struct ReplayVerifyCoordinator {
    storage: Arc<dyn BackupStorage>,
    metadata_cache_opt: MetadataCacheOpt,
    trusted_waypoints_opt: TrustedWaypointOpt,
    concurrent_downloads: usize,
    replay_concurrency_level: usize,
    restore_handler: RestoreHandler,
    start_version: Version,
    end_version: Version,
}

impl ReplayVerifyCoordinator {
    pub fn new(
        storage: Arc<dyn BackupStorage>,
        metadata_cache_opt: MetadataCacheOpt,
        trusted_waypoints_opt: TrustedWaypointOpt,
        concurrent_downloads: usize,
        replay_concurrency_level: usize,
        restore_handler: RestoreHandler,
        start_version: Version,
        end_version: Version,
    ) -> Result<Self> {
        Ok(Self {
            storage,
            metadata_cache_opt,
            trusted_waypoints_opt,
            concurrent_downloads,
            replay_concurrency_level,
            restore_handler,
            start_version,
            end_version,
        })
    }

    pub async fn run(self) -> Result<()> {
        info!("ReplayVerify coordinator started.");

        let ret = self.run_impl().await;

        if let Err(e) = &ret {
            error!(
                error = ?e,
                "ReplayVerify coordinator failed."
            );
        } else {
            info!("ReplayVerify coordinator exiting with success.");
        }

        ret
    }

    async fn run_impl(self) -> Result<()> {
        AptosVM::set_concurrency_level_once(self.replay_concurrency_level);

        let metadata_view = metadata::cache::sync_and_load(
            &self.metadata_cache_opt,
            Arc::clone(&self.storage),
            self.concurrent_downloads,
        )
        .await?;
        ensure!(
            self.start_version <= self.end_version,
            "start_version should precede end_version."
        );

        let state_snapshot = if self.start_version == 0 {
            None
        } else {
            metadata_view.select_state_snapshot(self.start_version.wrapping_sub(1))?
        };
        let replay_transactions_from_version = state_snapshot
            .as_ref()
            .map(|b| b.version.wrapping_add(1))
            .unwrap_or(0);
        let transactions = metadata_view
            .select_transaction_backups(replay_transactions_from_version, self.end_version)?;

        let global_opt = GlobalRestoreOptions {
            target_version: self.end_version,
            trusted_waypoints: Arc::new(self.trusted_waypoints_opt.verify()?),
            run_mode: Arc::new(RestoreRunMode::Restore {
                restore_handler: self.restore_handler,
            }),
            concurrent_downloads: self.concurrent_downloads,
            replay_concurrency_level: 0, // won't replay, doesn't matter
        };

        if let Some(backup) = state_snapshot {
            StateSnapshotRestoreController::new(
                StateSnapshotRestoreOpt {
                    manifest_handle: backup.manifest,
                    version: backup.version,
                },
                global_opt.clone(),
                Arc::clone(&self.storage),
                None, /* epoch_history */
            )
            .run()
            .await?;
        }

        let txn_manifests = transactions.into_iter().map(|b| b.manifest).collect();
        TransactionRestoreBatchController::new(
            global_opt,
            self.storage,
            txn_manifests,
            Some(replay_transactions_from_version), /* replay_from_version */
            None,                                   /* epoch_history */
        )
        .run()
        .await?;

        Ok(())
    }
}
<commit_msg>fix replay-verify<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    backup_types::{
        state_snapshot::restore::{StateSnapshotRestoreController, StateSnapshotRestoreOpt},
        transaction::restore::TransactionRestoreBatchController,
    },
    metadata,
    metadata::cache::MetadataCacheOpt,
    storage::BackupStorage,
    utils::{GlobalRestoreOptions, RestoreRunMode, TrustedWaypointOpt},
};
use anyhow::{ensure, Result};
use aptos_logger::prelude::*;
use aptos_types::transaction::Version;
use aptos_vm::AptosVM;
use aptosdb::backup::restore_handler::RestoreHandler;
use std::sync::Arc;

pub struct ReplayVerifyCoordinator {
    storage: Arc<dyn BackupStorage>,
    metadata_cache_opt: MetadataCacheOpt,
    trusted_waypoints_opt: TrustedWaypointOpt,
    concurrent_downloads: usize,
    replay_concurrency_level: usize,
    restore_handler: RestoreHandler,
    start_version: Version,
    end_version: Version,
}

impl ReplayVerifyCoordinator {
    pub fn new(
        storage: Arc<dyn BackupStorage>,
        metadata_cache_opt: MetadataCacheOpt,
        trusted_waypoints_opt: TrustedWaypointOpt,
        concurrent_downloads: usize,
        replay_concurrency_level: usize,
        restore_handler: RestoreHandler,
        start_version: Version,
        end_version: Version,
    ) -> Result<Self> {
        Ok(Self {
            storage,
            metadata_cache_opt,
            trusted_waypoints_opt,
            concurrent_downloads,
            replay_concurrency_level,
            restore_handler,
            start_version,
            end_version,
        })
    }

    pub async fn run(self) -> Result<()> {
        info!("ReplayVerify coordinator started.");

        let ret = self.run_impl().await;

        if let Err(e) = &ret {
            error!(
                error = ?e,
                "ReplayVerify coordinator failed."
            );
        } else {
            info!("ReplayVerify coordinator exiting with success.");
        }

        ret
    }

    async fn run_impl(self) -> Result<()> {
        AptosVM::set_concurrency_level_once(self.replay_concurrency_level);

        let metadata_view = metadata::cache::sync_and_load(
            &self.metadata_cache_opt,
            Arc::clone(&self.storage),
            self.concurrent_downloads,
        )
        .await?;
        ensure!(
            self.start_version <= self.end_version,
            "start_version should precede end_version."
        );

        let state_snapshot = if self.start_version == 0 {
            None
        } else {
            metadata_view.select_state_snapshot(self.start_version.wrapping_sub(1))?
        };
        let replay_transactions_from_version =
            state_snapshot.as_ref().map(|b| b.version).unwrap_or(0);
        let transactions = metadata_view.select_transaction_backups(
            // transaction info at the snapshot must be restored otherwise the db will be confused
            // about the latest version after snapshot is restored.
            replay_transactions_from_version.saturating_sub(1),
            self.end_version,
        )?;

        let global_opt = GlobalRestoreOptions {
            target_version: self.end_version,
            trusted_waypoints: Arc::new(self.trusted_waypoints_opt.verify()?),
            run_mode: Arc::new(RestoreRunMode::Restore {
                restore_handler: self.restore_handler,
            }),
            concurrent_downloads: self.concurrent_downloads,
            replay_concurrency_level: 0, // won't replay, doesn't matter
        };

        if let Some(backup) = state_snapshot {
            StateSnapshotRestoreController::new(
                StateSnapshotRestoreOpt {
                    manifest_handle: backup.manifest,
                    version: backup.version,
                },
                global_opt.clone(),
                Arc::clone(&self.storage),
                None, /* epoch_history */
            )
            .run()
            .await?;
        }

        let txn_manifests = transactions.into_iter().map(|b| b.manifest).collect();
        TransactionRestoreBatchController::new(
            global_opt,
            self.storage,
            txn_manifests,
            Some(replay_transactions_from_version), /* replay_from_version */
            None,                                   /* epoch_history */
        )
        .run()
        .await?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");

        // DEP_OPENSSL_ROOT was what cargo used to use via overrides, and
        // OPENSSL_ROOT_DIR is also used by libssh2 which cargo uses and can be
        // set by various build scripts.
        let openssl_root = env::var_os("DEP_OPENSSL_ROOT").or_else(|| {
            env::var_os("OPENSSL_ROOT_DIR")
        }).or_else(|| {
            env::var_os("DEP_OPENSSL_INCLUDE").and_then(|include| {
                let root = Path::new(&include).parent().unwrap();
                if root.exists() {
                    Some(root.as_os_str().to_owned())
                } else {
                    None
                }
            })
        });
        if let Some(s) = openssl_root {
            cmd.arg(format!("--with-ssl={}", s.to_str().unwrap()));
        }
    }
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        cmd.arg(format!("--host={}", host));
        cmd.arg(format!("--target={}", target));
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-nghttp2");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::hard_link(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<commit_msg>Try force enabling zlib<commit_after>extern crate pkg_config;
extern crate gcc;

use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::{PathBuf, Path};
use std::process::Command;
use std::io::ErrorKind;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(e) => panic!("{} return the error {}", stringify!($e), e),
    })
}

fn main() {
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let windows = target.contains("windows");

    // OSX ships libcurl by default, so we just use that version
    // unconditionally.
    if target.contains("apple") {
        return println!("cargo:rustc-flags=-l curl");
    }

    // Illumos/Solaris requires explicit linking with libnsl
    if target.contains("solaris") {
        println!("cargo:rustc-flags=-l nsl");
    }

    // Next, fall back and try to use pkg-config if its available.
    if !target.contains("windows") {
        match pkg_config::find_library("libcurl") {
            Ok(lib) => {
                for path in lib.include_paths.iter() {
                    println!("cargo:include={}", path.display());
                }
                return
            }
            Err(e) => println!("Couldn't find libcurl from \
                               pkgconfig ({:?}), compiling it from source...", e),
        }
    }

    if !Path::new("curl/.git").exists() {
        let _ = Command::new("git").args(&["submodule", "update", "--init"])
                                   .status();
    }

    println!("cargo:rustc-link-search={}/lib", dst.display());
    println!("cargo:rustc-link-lib=static=curl");
    println!("cargo:root={}", dst.display());
    println!("cargo:include={}/include", dst.display());
    if windows {
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=crypt32");
    }

    // MSVC builds are just totally different
    if target.contains("msvc") {
        return build_msvc(&target);
    }

    let cfg = gcc::Config::new();
    let compiler = cfg.get_compiler();

    let _ = fs::create_dir(&dst.join("build"));

    let mut cmd = Command::new("sh");
    let mut cflags = OsString::new();
    for arg in compiler.args() {
        cflags.push(arg);
        cflags.push(" ");
    }

    // Can't run ./configure directly on msys2 b/c we're handing in
    // Windows-style paths (those starting with C:\), but it chokes on those.
    // For that reason we build up a shell script with paths converted to
    // posix versions hopefully...
    //
    // Also apparently the buildbots choke unless we manually set LD, who knows
    // why?!
    cmd.env("CC", compiler.path())
       .env("CFLAGS", cflags)
       .env("LD", &which("ld").unwrap())
       .env("VERBOSE", "1")
       .current_dir(&dst.join("build"))
       .arg(msys_compatible(&src.join("curl/configure")));

    // For now this build script doesn't support paths with spaces in them. This
    // is arguably a but in curl's configure script, but we could also try to
    // paper over it by using a tmp directory which *doesn't* have spaces in it.
    // As of now though that's not implemented so just give a nicer error for
    // the time being.
    let wants_space_error = windows &&
        (dst.to_str().map(|s| s.contains(" ")).unwrap_or(false) ||
         src.to_str().map(|s| s.contains(" ")).unwrap_or(false));
    if wants_space_error {
        panic!("\n\nunfortunately ./configure of libcurl is known to \
                fail if there's a space in the path to the current \
                directory\n\n\
                there's a space in either\n  {}\n  {}\nand this will cause the \
                build to fail\n\n\
                the MSVC build should work with a directory that has \
                spaces in it, and it would also work to move this to a \
                different directory without spaces\n\n",
               src.display(), dst.display())
    }

    if windows {
        cmd.arg("--with-winssl");
    } else {
        cmd.arg("--without-ca-bundle");
        cmd.arg("--without-ca-path");

        // DEP_OPENSSL_ROOT was what cargo used to use via overrides, and
        // OPENSSL_ROOT_DIR is also used by libssh2 which cargo uses and can be
        // set by various build scripts.
        let openssl_root = env::var_os("DEP_OPENSSL_ROOT").or_else(|| {
            env::var_os("OPENSSL_ROOT_DIR")
        }).or_else(|| {
            env::var_os("DEP_OPENSSL_INCLUDE").and_then(|include| {
                let root = Path::new(&include).parent().unwrap();
                if root.exists() {
                    Some(root.as_os_str().to_owned())
                } else {
                    None
                }
            })
        });
        if let Some(s) = openssl_root {
            cmd.arg(format!("--with-ssl={}", s.to_str().unwrap()));
        }
    }
    if let Ok(root) = env::var("DEP_Z_ROOT") {
        cmd.arg(format!("--with-zlib={}", root));
    }
    cmd.arg("--enable-static=yes");
    cmd.arg("--enable-shared=no");
    match &env::var("PROFILE").unwrap()[..] {
        "bench" | "release" => {
            cmd.arg("--enable-optimize");
        }
        _ => {
            cmd.arg("--enable-debug");
            cmd.arg("--disable-optimize");
        }
    }
    cmd.arg(format!("--prefix={}", msys_compatible(&dst)));

    if target != host &&
       (!target.contains("windows") || !host.contains("windows")) {
        cmd.arg(format!("--host={}", host));
        cmd.arg(format!("--target={}", target));
    }

    cmd.arg("--without-librtmp");
    cmd.arg("--without-libidn");
    cmd.arg("--without-libssh2");
    cmd.arg("--without-nghttp2");
    cmd.arg("--disable-ldap");
    cmd.arg("--disable-ldaps");
    cmd.arg("--disable-ftp");
    cmd.arg("--disable-rtsp");
    cmd.arg("--disable-dict");
    cmd.arg("--disable-telnet");
    cmd.arg("--disable-tftp");
    cmd.arg("--disable-pop3");
    cmd.arg("--disable-imap");
    cmd.arg("--disable-smtp");
    cmd.arg("--disable-gopher");
    cmd.arg("--disable-manual");
    cmd.arg("--disable-smb");
    cmd.arg("--disable-sspi");

    run(&mut cmd, "sh");
    run(Command::new(make())
                .arg(&format!("-j{}", env::var("NUM_JOBS").unwrap()))
                .current_dir(&dst.join("build")), "make");
    run(Command::new(make())
                .arg("install")
                .current_dir(&dst.join("build")), "make");
}

fn run(cmd: &mut Command, program: &str) {
    println!("running: {:?}", cmd);
    let status = match cmd.status() {
        Ok(status) => status,
        Err(ref e) if e.kind() == ErrorKind::NotFound => {
            fail(&format!("failed to execute command: {}\nis `{}` not installed?",
                          e, program));
        }
        Err(e) => fail(&format!("failed to execute command: {}", e)),
    };
    if !status.success() {
        fail(&format!("command did not execute successfully, got: {}", status));
    }
}

fn fail(s: &str) -> ! {
    panic!("\n{}\n\nbuild script failed, must exit now", s)
}

fn make() -> &'static str {
    if cfg!(target_os = "freebsd") {"gmake"} else {"make"}
}

fn which(cmd: &str) -> Option<PathBuf> {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let paths = env::var_os("PATH").unwrap();
    env::split_paths(&paths).map(|p| p.join(&cmd)).find(|p| {
        fs::metadata(p).is_ok()
    })
}

fn msys_compatible(path: &Path) -> String {
    let path = path.to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string()
    }
    path.replace("C:\\", "/c/")
        .replace("\\", "/")
}

fn build_msvc(target: &str) {
    let cmd = gcc::windows_registry::find(target, "nmake.exe");
    let mut cmd = cmd.unwrap_or(Command::new("nmake.exe"));
    let src = env::current_dir().unwrap();
    let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let machine = if target.starts_with("x86_64") {
        "x64"
    } else if target.starts_with("i686") {
        "x86"
    } else {
        panic!("unknown msvc target: {}", target);
    };

    t!(fs::create_dir_all(dst.join("include/curl")));
    t!(fs::create_dir_all(dst.join("lib")));

    cmd.current_dir(src.join("curl/winbuild"));
    cmd.arg("/f").arg("Makefile.vc")
       .arg("MODE=static")
       .arg("ENABLE_IDN=yes")
       .arg("DEBUG=no")
       .arg("GEN_PDB=no")
       .arg("ENABLE_WINSSL=yes")
       .arg("ENABLE_SSPI=yes")
       .arg(format!("MACHINE={}", machine));

    if let Some(inc) = env::var_os("DEP_Z_ROOT") {
        let inc = PathBuf::from(inc);
        let mut s = OsString::from("WITH_DEVEL=");
        s.push(&inc);
        cmd.arg("WITH_ZLIB=static").arg(s);

        // the build system for curl expects this library to be called
        // zlib_a.lib, so make sure it's named correctly (where libz-sys just
        // produces zlib.lib)
        let _ = fs::remove_file(&inc.join("lib/zlib_a.lib"));
        t!(fs::hard_link(inc.join("lib/zlib.lib"), inc.join("lib/zlib_a.lib")));
    }
    run(&mut cmd, "nmake");

    let name = format!("libcurl-vc-{}-release-static-zlib-static-\
                        ipv6-sspi-winssl", machine);
    let libs = src.join("curl/builds").join(name);

    t!(fs::copy(libs.join("lib/libcurl_a.lib"), dst.join("lib/curl.lib")));
    for f in t!(fs::read_dir(libs.join("include/curl"))) {
        let path = t!(f).path();
        let dst = dst.join("include/curl").join(path.file_name().unwrap());
        t!(fs::copy(path, dst));
    }
    t!(fs::remove_dir_all(src.join("curl/builds")));
    println!("cargo:rustc-link-lib=wldap32");
    println!("cargo:rustc-link-lib=advapi32");
    println!("cargo:rustc-link-lib=normaliz");
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use clean::*;
use std::iter::Extend;
use std::mem::{replace, swap};

pub trait DocFolder {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        self.fold_item_recur(item)
    }

    /// don't override!
    fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
        let Item { attrs, name, source, visibility, def_id, inner, stability } = item;
        let inner = inner;
        let inner = match inner {
            StructItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.fields);
                let num_fields = foo.len();
                i.fields.extend(foo.into_iter().filter_map(|x| self.fold_item(x)));
                i.fields_stripped |= num_fields != i.fields.len();
                StructItem(i)
            },
            ModuleItem(i) => {
                ModuleItem(self.fold_mod(i))
            },
            EnumItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.variants);
                let num_variants = foo.len();
                i.variants.extend(foo.into_iter().filter_map(|x| self.fold_item(x)));
                i.variants_stripped |= num_variants != i.variants.len();
                EnumItem(i)
            },
            TraitItem(mut i) => {
                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod)
                        -> Option<TraitMethod> {
                    match trm {
                        RequiredMethod(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(RequiredMethod(x)),
                                None => return None,
                            }
                        },
                        ProvidedMethod(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(ProvidedMethod(x)),
                                None => return None,
                            }
                        },
                        TypeTraitItem(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(TypeTraitItem(x)),
                                None => return None,
                            }
                        }
                    }
                }
                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
                i.items.extend(foo.into_iter().filter_map(|x| vtrm(self, x)));
                TraitItem(i)
            },
            ImplItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
                i.items.extend(foo.into_iter()
                                  .filter_map(|x| self.fold_item(x)));
                ImplItem(i)
            },
            VariantItem(i) => {
                let i2 = i.clone(); // this clone is small
                match i.kind {
                    StructVariant(mut j) => {
                        let mut foo = Vec::new(); swap(&mut foo, &mut j.fields);
                        let num_fields = foo.len();
                        let c = |x| self.fold_item(x);
                        j.fields.extend(foo.into_iter().filter_map(c));
                        j.fields_stripped |= num_fields != j.fields.len();
                        VariantItem(Variant {kind: StructVariant(j), ..i2})
                    },
                    _ => VariantItem(i2)
                }
            },
            x => x
        };

        Some(Item { attrs: attrs, name: name, source: source, inner: inner,
                    visibility: visibility, stability: stability, def_id: def_id })
    }

    fn fold_mod(&mut self, m: Module) -> Module {
        Module {
            is_crate: m.is_crate,
            items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect()
        }
    }

    fn fold_crate(&mut self, mut c: Crate) -> Crate {
        c.module = match replace(&mut c.module, None) {
            Some(module) => self.fold_item(module), None => None
        };
        return c;
    }
}
<commit_msg>librustdoc: fix fallout<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use clean::*;
use std::iter::Extend;
use std::mem::{replace, swap};

pub trait DocFolder {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        self.fold_item_recur(item)
    }

    /// don't override!
    fn fold_item_recur(&mut self, item: Item) -> Option<Item> {
        let Item { attrs, name, source, visibility, def_id, inner, stability } = item;
        let inner = inner;
        let inner = match inner {
            StructItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.fields);
                let num_fields = foo.len();
                i.fields.extend(foo.into_iter().filter_map(|x| self.fold_item(x)));
                i.fields_stripped |= num_fields != i.fields.len();
                StructItem(i)
            },
            ModuleItem(i) => {
                ModuleItem(self.fold_mod(i))
            },
            EnumItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.variants);
                let num_variants = foo.len();
                i.variants.extend(foo.into_iter().filter_map(|x| self.fold_item(x)));
                i.variants_stripped |= num_variants != i.variants.len();
                EnumItem(i)
            },
            TraitItem(mut i) => {
                fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod)
                        -> Option<TraitMethod> {
                    match trm {
                        RequiredMethod(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(RequiredMethod(x)),
                                None => return None,
                            }
                        },
                        ProvidedMethod(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(ProvidedMethod(x)),
                                None => return None,
                            }
                        },
                        TypeTraitItem(it) => {
                            match this.fold_item(it) {
                                Some(x) => return Some(TypeTraitItem(x)),
                                None => return None,
                            }
                        }
                    }
                }
                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
                i.items.extend(foo.into_iter().filter_map(|x| vtrm(self, x)));
                TraitItem(i)
            },
            ImplItem(mut i) => {
                let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
                i.items.extend(foo.into_iter()
                                  .filter_map(|x| self.fold_item(x)));
                ImplItem(i)
            },
            VariantItem(i) => {
                let i2 = i.clone(); // this clone is small
                match i.kind {
                    StructVariant(mut j) => {
                        let mut foo = Vec::new(); swap(&mut foo, &mut j.fields);
                        let num_fields = foo.len();
                        j.fields.extend(foo.into_iter().filter_map(|x| self.fold_item(x)));
                        j.fields_stripped |= num_fields != j.fields.len();
                        VariantItem(Variant {kind: StructVariant(j), ..i2})
                    },
                    _ => VariantItem(i2)
                }
            },
            x => x
        };

        Some(Item { attrs: attrs, name: name, source: source, inner: inner,
                    visibility: visibility, stability: stability, def_id: def_id })
    }

    fn fold_mod(&mut self, m: Module) -> Module {
        Module {
            is_crate: m.is_crate,
            items: m.items.into_iter().filter_map(|i| self.fold_item(i)).collect()
        }
    }

    fn fold_crate(&mut self, mut c: Crate) -> Crate {
        c.module = match replace(&mut c.module, None) {
            Some(module) => self.fold_item(module), None => None
        };
        return c;
    }
}
<|endoftext|>


<commit_before>use rustc_data_structures::fx::FxHashMap;
use rustc_lint::LintStore;
use rustc_lint_defs::{declare_tool_lint, Lint, LintId};
use rustc_session::{lint, Session};

use std::lazy::SyncLazy as Lazy;

/// This function is used to setup the lint initialization. By default, in rustdoc, everything
/// is "allowed". Depending if we run in test mode or not, we want some of them to be at their
/// default level. For example, the "INVALID_CODEBLOCK_ATTRIBUTES" lint is activated in both
/// modes.
///
/// A little detail easy to forget is that there is a way to set the lint level for all lints
/// through the "WARNINGS" lint. To prevent this to happen, we set it back to its "normal" level
/// inside this function.
///
/// It returns a tuple containing:
///  * Vector of tuples of lints' name and their associated "max" level
///  * HashMap of lint id with their associated "max" level
pub(crate) fn init_lints<F>(
    mut allowed_lints: Vec<String>,
    lint_opts: Vec<(String, lint::Level)>,
    filter_call: F,
) -> (Vec<(String, lint::Level)>, FxHashMap<lint::LintId, lint::Level>)
where
    F: Fn(&lint::Lint) -> Option<(String, lint::Level)>,
{
    let warnings_lint_name = lint::builtin::WARNINGS.name;

    allowed_lints.push(warnings_lint_name.to_owned());
    allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());

    let lints = || {
        lint::builtin::HardwiredLints::get_lints()
            .into_iter()
            .chain(rustc_lint::SoftLints::get_lints().into_iter())
    };

    let lint_opts = lints()
        .filter_map(|lint| {
            // Permit feature-gated lints to avoid feature errors when trying to
            // allow all lints.
            if lint.feature_gate.is_some() || allowed_lints.iter().any(|l| lint.name == l) {
                None
            } else {
                filter_call(lint)
            }
        })
        .chain(lint_opts.into_iter())
        .collect::<Vec<_>>();

    let lint_caps = lints()
        .filter_map(|lint| {
            // We don't want to allow *all* lints so let's ignore
            // those ones.
            if allowed_lints.iter().any(|l| lint.name == l) {
                None
            } else {
                Some((lint::LintId::of(lint), lint::Allow))
            }
        })
        .collect();
    (lint_opts, lint_caps)
}

declare_tool_lint! {
    /// The `broken_intra_doc_links` lint detects failures in resolving
    /// intra-doc link targets. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links
    pub rustdoc::BROKEN_INTRA_DOC_LINKS,
    Warn,
    "failures in resolving intra-doc link targets"
}

declare_tool_lint! {
    /// This is a subset of `broken_intra_doc_links` that warns when linking from
    /// a public item to a private one. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#private_intra_doc_links
    pub rustdoc::PRIVATE_INTRA_DOC_LINKS,
    Warn,
    "linking from a public item to a private one"
}

declare_tool_lint! {
    /// The `invalid_codeblock_attributes` lint detects code block attributes
    /// in documentation examples that have potentially mis-typed values. This
    /// is a `rustdoc` only lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#invalid_codeblock_attributes
    pub rustdoc::INVALID_CODEBLOCK_ATTRIBUTES,
    Warn,
    "codeblock attribute looks a lot like a known one"
}

declare_tool_lint! {
    /// The `missing_doc_code_examples` lint detects publicly-exported items
    /// without code samples in their documentation. This is a `rustdoc` only
    /// lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
    pub rustdoc::MISSING_DOC_CODE_EXAMPLES,
    Allow,
    "detects publicly-exported items without code samples in their documentation"
}

declare_tool_lint! {
    /// The `private_doc_tests` lint detects code samples in docs of private
    /// items not documented by `rustdoc`. This is a `rustdoc` only lint, see
    /// the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#private_doc_tests
    pub rustdoc::PRIVATE_DOC_TESTS,
    Allow,
    "detects code samples in docs of private items not documented by rustdoc"
}

declare_tool_lint! {
    /// The `invalid_html_tags` lint detects invalid HTML tags. This is a
    /// `rustdoc` only lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#invalid_html_tags
    pub rustdoc::INVALID_HTML_TAGS,
    Allow,
    "detects invalid HTML tags in doc comments"
}

declare_tool_lint! {
    /// The `non_autolinks` lint detects when a URL could be written using
    /// only angle brackets. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#non_autolinks
    pub rustdoc::NON_AUTOLINKS,
    Warn,
    "detects URLs that could be written using only angle brackets"
}

crate static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
    vec![
        BROKEN_INTRA_DOC_LINKS,
        PRIVATE_INTRA_DOC_LINKS,
        MISSING_DOC_CODE_EXAMPLES,
        PRIVATE_DOC_TESTS,
        INVALID_CODEBLOCK_ATTRIBUTES,
        INVALID_HTML_TAGS,
        NON_AUTOLINKS,
    ]
});

crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
    lint_store.register_lints(&**RUSTDOC_LINTS);
    lint_store.register_group(
        true,
        "rustdoc",
        None,
        RUSTDOC_LINTS.iter().map(|&lint| LintId::of(lint)).collect(),
    );
    lint_store
        .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
}
<commit_msg>Add `declare_rustdoc_lint!` macro<commit_after>use rustc_data_structures::fx::FxHashMap;
use rustc_lint::LintStore;
use rustc_lint_defs::{declare_tool_lint, Lint, LintId};
use rustc_session::{lint, Session};

use std::lazy::SyncLazy as Lazy;

/// This function is used to setup the lint initialization. By default, in rustdoc, everything
/// is "allowed". Depending if we run in test mode or not, we want some of them to be at their
/// default level. For example, the "INVALID_CODEBLOCK_ATTRIBUTES" lint is activated in both
/// modes.
///
/// A little detail easy to forget is that there is a way to set the lint level for all lints
/// through the "WARNINGS" lint. To prevent this to happen, we set it back to its "normal" level
/// inside this function.
///
/// It returns a tuple containing:
///  * Vector of tuples of lints' name and their associated "max" level
///  * HashMap of lint id with their associated "max" level
pub(crate) fn init_lints<F>(
    mut allowed_lints: Vec<String>,
    lint_opts: Vec<(String, lint::Level)>,
    filter_call: F,
) -> (Vec<(String, lint::Level)>, FxHashMap<lint::LintId, lint::Level>)
where
    F: Fn(&lint::Lint) -> Option<(String, lint::Level)>,
{
    let warnings_lint_name = lint::builtin::WARNINGS.name;

    allowed_lints.push(warnings_lint_name.to_owned());
    allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());

    let lints = || {
        lint::builtin::HardwiredLints::get_lints()
            .into_iter()
            .chain(rustc_lint::SoftLints::get_lints().into_iter())
    };

    let lint_opts = lints()
        .filter_map(|lint| {
            // Permit feature-gated lints to avoid feature errors when trying to
            // allow all lints.
            if lint.feature_gate.is_some() || allowed_lints.iter().any(|l| lint.name == l) {
                None
            } else {
                filter_call(lint)
            }
        })
        .chain(lint_opts.into_iter())
        .collect::<Vec<_>>();

    let lint_caps = lints()
        .filter_map(|lint| {
            // We don't want to allow *all* lints so let's ignore
            // those ones.
            if allowed_lints.iter().any(|l| lint.name == l) {
                None
            } else {
                Some((lint::LintId::of(lint), lint::Allow))
            }
        })
        .collect();
    (lint_opts, lint_caps)
}

macro_rules! declare_rustdoc_lint {
    ($(#[$attr:meta])* $name: ident, $level: ident, $descr: literal $(,)?) => {
        declare_tool_lint! {
            $(#[$attr])* pub rustdoc::$name, $level, $descr
        }
    }
}

declare_rustdoc_lint! {
    /// The `broken_intra_doc_links` lint detects failures in resolving
    /// intra-doc link targets. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links
    BROKEN_INTRA_DOC_LINKS,
    Warn,
    "failures in resolving intra-doc link targets"
}

declare_rustdoc_lint! {
    /// This is a subset of `broken_intra_doc_links` that warns when linking from
    /// a public item to a private one. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#private_intra_doc_links
    PRIVATE_INTRA_DOC_LINKS,
    Warn,
    "linking from a public item to a private one"
}

declare_rustdoc_lint! {
    /// The `invalid_codeblock_attributes` lint detects code block attributes
    /// in documentation examples that have potentially mis-typed values. This
    /// is a `rustdoc` only lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#invalid_codeblock_attributes
    INVALID_CODEBLOCK_ATTRIBUTES,
    Warn,
    "codeblock attribute looks a lot like a known one"
}

declare_rustdoc_lint! {
    /// The `missing_doc_code_examples` lint detects publicly-exported items
    /// without code samples in their documentation. This is a `rustdoc` only
    /// lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
    MISSING_DOC_CODE_EXAMPLES,
    Allow,
    "detects publicly-exported items without code samples in their documentation"
}

declare_rustdoc_lint! {
    /// The `private_doc_tests` lint detects code samples in docs of private
    /// items not documented by `rustdoc`. This is a `rustdoc` only lint, see
    /// the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#private_doc_tests
    PRIVATE_DOC_TESTS,
    Allow,
    "detects code samples in docs of private items not documented by rustdoc"
}

declare_rustdoc_lint! {
    /// The `invalid_html_tags` lint detects invalid HTML tags. This is a
    /// `rustdoc` only lint, see the documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#invalid_html_tags
    INVALID_HTML_TAGS,
    Allow,
    "detects invalid HTML tags in doc comments"
}

declare_rustdoc_lint! {
    /// The `non_autolinks` lint detects when a URL could be written using
    /// only angle brackets. This is a `rustdoc` only lint, see the
    /// documentation in the [rustdoc book].
    ///
    /// [rustdoc book]: ../../../rustdoc/lints.html#non_autolinks
    NON_AUTOLINKS,
    Warn,
    "detects URLs that could be written using only angle brackets"
}

crate static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
    vec![
        BROKEN_INTRA_DOC_LINKS,
        PRIVATE_INTRA_DOC_LINKS,
        MISSING_DOC_CODE_EXAMPLES,
        PRIVATE_DOC_TESTS,
        INVALID_CODEBLOCK_ATTRIBUTES,
        INVALID_HTML_TAGS,
        NON_AUTOLINKS,
    ]
});

crate fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
    lint_store.register_lints(&**RUSTDOC_LINTS);
    lint_store.register_group(
        true,
        "rustdoc",
        None,
        RUSTDOC_LINTS.iter().map(|&lint| LintId::of(lint)).collect(),
    );
    lint_store
        .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
}
<|endoftext|>


<commit_before>#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate clap;

extern crate libimagcounter;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use std::process::exit;
use std::str::FromStr;

use libimagrt::runtime::Runtime;
use libimagcounter::counter::Counter;
use libimagerror::trace::trace_error;
use libimagutil::key_value_split::IntoKeyValue;

mod create;
mod delete;
mod interactive;
mod list;
mod ui;

use ui::build_ui;
use create::create;
use delete::delete;
use interactive::interactive;
use list::list;

enum Action {
    Inc,
    Dec,
    Reset,
    Set,
}

fn main() {
    let name = "imag-counter";
    let version = &version!()[..];
    let about = "Counter tool to count things";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    rt.cli()
        .subcommand_name()
        .map_or_else(|| {
                let (action, name) = {
                    if rt.cli().is_present("increment") {
                        (Action::Inc, rt.cli().value_of("increment").unwrap())
                    } else if rt.cli().is_present("decrement") {
                        (Action::Dec, rt.cli().value_of("decrement").unwrap())
                    } else if rt.cli().is_present("reset") {
                        (Action::Reset, rt.cli().value_of("reset").unwrap())
                    } else /* rt.cli().is_present("set") */ {
                        (Action::Set, rt.cli().value_of("set").unwrap())
                    }
                };

                match action {
                    Action::Inc => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.inc() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Dec => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.dec() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Reset => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.reset() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Set => {
                        let kv = String::from(name).into_kv();
                        if kv.is_none() {
                            warn!("Not a key-value pair: '{}'", name);
                            exit(1);
                        }
                        let (key, value) = kv.unwrap().into();
                        let value = FromStr::from_str(&value[..]);
                        if value.is_err() {
                            warn!("Not a integer: '{:?}'", value);
                            exit(1);
                        }
                        let value : i64 = value.unwrap();
                        Counter::load(String::from(key), rt.store())
                            .map(|mut counter| {
                                match counter.set(value) {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                }
                .map_err(|e| trace_error(&e))
                .ok();
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "create"      => create(&rt),
                    "delete"      => delete(&rt),
                    "interactive" => interactive(&rt),
                    "list"        => list(&rt),
                    _ => {
                        debug!("Unknown command"); // More error handling
                    },
                };
            })
}

<commit_msg>imag-counter: Remove setup code and use helper<commit_after>#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate clap;

extern crate libimagcounter;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use std::process::exit;
use std::str::FromStr;

use libimagrt::setup::generate_runtime_setup;
use libimagcounter::counter::Counter;
use libimagerror::trace::trace_error;
use libimagutil::key_value_split::IntoKeyValue;

mod create;
mod delete;
mod interactive;
mod list;
mod ui;

use ui::build_ui;
use create::create;
use delete::delete;
use interactive::interactive;
use list::list;

enum Action {
    Inc,
    Dec,
    Reset,
    Set,
}

fn main() {
    let rt = generate_runtime_setup("imag-counter",
                                    &version!()[..],
                                    "Counter tool to count things",
                                    build_ui);

    rt.cli()
        .subcommand_name()
        .map_or_else(|| {
                let (action, name) = {
                    if rt.cli().is_present("increment") {
                        (Action::Inc, rt.cli().value_of("increment").unwrap())
                    } else if rt.cli().is_present("decrement") {
                        (Action::Dec, rt.cli().value_of("decrement").unwrap())
                    } else if rt.cli().is_present("reset") {
                        (Action::Reset, rt.cli().value_of("reset").unwrap())
                    } else /* rt.cli().is_present("set") */ {
                        (Action::Set, rt.cli().value_of("set").unwrap())
                    }
                };

                match action {
                    Action::Inc => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.inc() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Dec => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.dec() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Reset => {
                        Counter::load(String::from(name), rt.store())
                            .map(|mut counter| {
                                match counter.reset() {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                    Action::Set => {
                        let kv = String::from(name).into_kv();
                        if kv.is_none() {
                            warn!("Not a key-value pair: '{}'", name);
                            exit(1);
                        }
                        let (key, value) = kv.unwrap().into();
                        let value = FromStr::from_str(&value[..]);
                        if value.is_err() {
                            warn!("Not a integer: '{:?}'", value);
                            exit(1);
                        }
                        let value : i64 = value.unwrap();
                        Counter::load(String::from(key), rt.store())
                            .map(|mut counter| {
                                match counter.set(value) {
                                    Err(e) => { trace_error(&e); exit(1); },
                                    Ok(_) => info!("Ok"),
                                }
                            })
                    },
                }
                .map_err(|e| trace_error(&e))
                .ok();
            },
            |name| {
                debug!("Call: {}", name);
                match name {
                    "create"      => create(&rt),
                    "delete"      => delete(&rt),
                    "interactive" => interactive(&rt),
                    "list"        => list(&rt),
                    _ => {
                        debug!("Unknown command"); // More error handling
                    },
                };
            })
}

<|endoftext|>