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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use std::{
    fs::{self},
    sync::{Arc, Mutex},
};

use anyhow::Error;
use fluentci_core::deps::{Graph, GraphCommand};
use fluentci_ext::git::Git as GitExt;
use fluentci_ext::git_checkout::GitCheckout as GitCheckoutExt;
use fluentci_ext::git_last_commit::GitLastCommit as GitLastCommitExt;
use fluentci_ext::runner::Runner as RunnerExt;
use fluentci_types::{directory::Directory, git::Git};
use uuid::Uuid;

use crate::util::{extract_git_repo, validate_git_url};

pub fn git(graph: Arc<Mutex<Graph>>, url: String, reset: bool) -> Result<Git, Error> {
    let mut graph = graph.lock().unwrap();

    if reset {
        graph.reset();
    }

    graph.runner = Arc::new(Box::new(GitExt::default()));
    graph.runner.setup()?;
    graph.work_dir = format!(
        "{}/.fluentci/cache",
        dirs::home_dir().unwrap().to_str().unwrap()
    );

    if !validate_git_url(&url) {
        return Err(Error::msg("Invalid git url"));
    }
    let repo = extract_git_repo(&url);
    graph.work_dir = format!("{}/{}", graph.work_dir, repo);

    fs::create_dir_all(&graph.work_dir)?;

    let id = Uuid::new_v4().to_string();
    graph.execute(GraphCommand::AddVertex(
        id.clone(),
        "git".into(),
        url.clone(),
        vec![],
        Arc::new(Box::new(GitExt::default())),
    ));
    graph.execute_vertex(&id)?;
    graph.work_dir = format!(
        "{}/{}",
        graph.work_dir,
        url.split("/").last().unwrap().replace(".git", "")
    );
    let git = Git { id };
    Ok(git)
}

pub fn branch(graph: Arc<Mutex<Graph>>, name: String) -> Result<(), Error> {
    let mut graph = graph.lock().unwrap();
    graph.runner = Arc::new(Box::new(GitCheckoutExt::default()));
    graph.runner.setup()?;

    let id = Uuid::new_v4().to_string();

    let dep_id = graph.vertices[graph.size() - 1].id.clone();
    let deps = match graph.size() {
        1 => vec![],
        _ => vec![dep_id],
    };
    graph.execute(GraphCommand::AddVertex(
        id.clone(),
        "git-checkout".into(),
        name,
        deps,
        Arc::new(Box::new(GitCheckoutExt::default())),
    ));
    graph.execute_vertex(&id)?;

    if graph.size() > 2 {
        let x = graph.size() - 2;
        let y = graph.size() - 1;
        graph.execute(GraphCommand::AddEdge(x, y));
    }
    Ok(())
}

pub fn commit(graph: Arc<Mutex<Graph>>) -> Result<String, Error> {
    let mut graph = graph.lock().unwrap();
    graph.runner = Arc::new(Box::new(GitLastCommitExt::default()));
    graph.runner.setup()?;

    let id = Uuid::new_v4().to_string();

    let dep_id = graph.vertices[graph.size() - 1].id.clone();
    let deps = match graph.size() {
        1 => vec![],
        _ => vec![dep_id],
    };
    graph.execute(GraphCommand::AddVertex(
        id.clone(),
        "git-last-commit".into(),
        "".into(),
        deps,
        Arc::new(Box::new(GitLastCommitExt::default())),
    ));

    if graph.size() > 2 {
        let x = graph.size() - 2;
        let y = graph.size() - 1;
        graph.execute(GraphCommand::AddEdge(x, y));
    }

    graph.execute_vertex(&id)
}

pub fn tree(graph: Arc<Mutex<Graph>>) -> Result<Directory, Error> {
    let id = Uuid::new_v4().to_string();
    let mut graph = graph.lock().unwrap();

    let dep_id = graph.vertices[graph.size() - 1].id.clone();

    graph.execute(GraphCommand::AddVertex(
        id.clone(),
        "tree".into(),
        "".into(),
        vec![dep_id],
        Arc::new(Box::new(RunnerExt::default())),
    ));

    let x = graph.size() - 2;
    let y = graph.size() - 1;
    graph.execute(GraphCommand::AddEdge(x, y));
    graph.runner = Arc::new(Box::new(RunnerExt::default()));

    let path = graph.work_dir.clone();

    graph.execute(GraphCommand::AddVolume(
        id.clone(),
        "directory".into(),
        path.clone(),
    ));

    let directory = Directory { id, path };

    Ok(directory)
}