-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.rs
135 lines (112 loc) · 4.15 KB
/
main.rs
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
#![forbid(unsafe_code)]
mod cli;
mod fail;
mod release;
mod types;
mod upload;
use std::{
env::set_current_dir,
fs::{self, File},
io::Cursor,
path::Path,
};
use anyhow::{Context, Result};
use clap::Parser;
use globset::{Glob, GlobSetBuilder};
use rpassword::prompt_password;
use serde::Serialize;
use walkdir::WalkDir;
use crate::{
cli::Opts,
types::{Config, Info},
};
fn main() -> Result<()> {
let opts = Opts::parse();
if let Some(dir) = opts.dir {
set_current_dir(&dir).with_context(fail::set_dir(dir.display()))?;
}
let cfg: Config = toml::from_str(
&fs::read_to_string(&opts.input).with_context(fail::read(opts.input.display()))?,
)
.with_context(fail::parse_cfg(opts.input.display()))?;
let mut include = GlobSetBuilder::new();
for pat in &cfg.source.include {
include.add(Glob::new(pat).with_context(fail::parse_glob(pat))?);
}
let include = include.build().context("Failed to build glob set")?;
let mut ignore = GlobSetBuilder::new();
for pat in &cfg.source.ignore {
ignore.add(Glob::new(pat).with_context(fail::parse_glob(pat))?);
}
let ignore = ignore.build().context("Failed to build glob set")?;
let mut files = Vec::new();
for entry in WalkDir::new(&cfg.source.dir).min_depth(1) {
let entry = entry
.with_context(fail::traverse(&cfg.source.dir))?
.into_path();
if include.is_match(&entry) && !ignore.is_match(&entry) {
files.push((
entry.clone(),
entry
.strip_prefix(&cfg.source.dir)
.with_context(fail::traverse(&cfg.source.dir))?
.into(),
));
}
}
let info = Info::from(cfg.clone());
let info = if opts.compact {
serde_json::to_vec(&info).context("Failed to generate info.json")?
} else {
let mut writer = Vec::with_capacity(256);
info.serialize(&mut serde_json::Serializer::with_formatter(
&mut writer,
serde_json::ser::PrettyFormatter::with_indent(b" "),
))
.context("Failed to generate info.json")?;
writer
};
let file_name = &format!("{}_{}", cfg.package.name, cfg.package.version);
if let Some(api_key) = opts.upload {
let mut zip = Cursor::new(Vec::with_capacity(256));
release::zip(
files,
info,
&mut zip,
file_name.into(),
opts.compression.into(),
)?;
if opts.zip {
fs::create_dir_all(&opts.output)
.with_context(fail::create_dir(opts.output.display()))?;
let output = &Path::new(&opts.output).join(format!("{file_name}.zip"));
release::remove_path(output)?;
let mut file =
File::create(output).with_context(fail::create_file(output.display()))?;
std::io::copy(&mut &zip.get_ref()[..], &mut file)
.context("Failed to write to the zip file")?;
}
let mod_name = &cfg.package.name;
let mod_version = &cfg.package.version;
let api_key = if let Some(x) = api_key {
x
} else {
prompt_password("API key: ").context("Failed to prompt for api key")?
};
upload::upload_mod(mod_name, &api_key, &zip.into_inner())
.with_context(fail::upload(mod_name, mod_version))?;
eprintln!("{mod_name} version {mod_version} was uploaded successfully");
} else if opts.zip {
fs::create_dir_all(&opts.output).with_context(fail::create_dir(opts.output.display()))?;
let output = &Path::new(&opts.output).join(format!("{file_name}.zip"));
release::remove_path(output)?;
let file = File::create(output).with_context(fail::create_file(output.display()))?;
release::zip(files, info, file, file_name.into(), opts.compression.into())?;
} else {
let output = &Path::new(&opts.output).join(file_name);
release::remove_path(output)?;
fs::create_dir_all(output).with_context(fail::create_dir(output.display()))?;
release::folder(files, info, output)?;
}
Ok(())
}