1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::fmt::{Display, Error, Formatter};

use crate::step::Step;
use rusty_yaml::Yaml;
use std::path::PathBuf;


const START_DIR: &str = "./build";


#[allow(dead_code)]
pub struct Builder {
    name: String,
    workernames: Vec<String>,
    steps: Vec<Step>,
}


// Implementation for Builder struct
impl Builder {
    // Create new builder
    fn new<S>(name: S, workernames: Vec<S>, steps: Vec<Step>) -> Self
    where
        S: Display,
    {
        Self {
            name: name.to_string(),
            workernames: workernames.iter().map(|s| s.to_string()).collect(),
            steps: steps,
        }
    }

    pub fn get_name(&self) -> String {
        self.name.clone()
    }
}


// How to convert Builder to a String / how to Format
impl Display for Builder {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(
            f,
            "
temp_factory = util.BuildFactory()
{steps}
c['builders'].append(
    util.BuilderConfig(name=\"{name}\",
    workernames={:?},
    factory=temp_factory))
        ",
            self.workernames,
            name = self.name,
            steps = self
                .steps
                .iter()
                .map(|s| { format!("temp_factory.addStep({})", s) })
                .collect::<Vec<String>>()
                .join("\n"),
        )
    }
}


impl From<Yaml> for Builder {
    fn from(yaml: Yaml) -> Builder {
        let name = yaml.get_name();

        for section in ["workers", "script", "repo"].iter() {
            assert!(
                yaml.has_section(section),
                format!("{} section not specified for {} builder", section, name)
            )
        }


        let mut steps: Vec<Step> = vec![];
        let mut workdir = PathBuf::new();
        workdir.push(START_DIR);
        let mut workers: Vec<String> = vec![];

        let url: String =
            yaml.get_section("repo").into_iter().collect::<Vec<Yaml>>()[0].to_string();

        steps.push(Step::git_clone(url));


        for instruction in yaml.get_section("script") {
            match instruction
                .to_string()
                .split_whitespace()
                .collect::<Vec<&str>>()[..]
            {
                ["cd", path] => workdir.push(path),
                _ => steps.push(Step::command(
                    instruction.to_string(),
                    match workdir.to_str() {
                        Some(s) => Some(s.to_string()),
                        None => None,
                    },
                )),
            };
        }

        for worker in yaml.get_section("workers") {
            workers.push(worker.to_string());
        }


        Builder::new(name, workers, steps)
    }
}