blob: 7b4beec20c29a182e3c51d10287aa5abe82e68b2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use chrono::{DateTime, Local};
use clap::Parser;
use serde::Serialize;
use std::{fs, path::PathBuf, process::Command, time::SystemTime};
use tera::{Context, Tera};
use tracing::info;
/// Create package.xml from template file.
#[derive(Parser, Debug)]
pub struct CreatePackageXmlCommand {
/// Template file path.
#[clap(long, default_value = "./package.tpl.xml")]
tpl_path: PathBuf,
/// Target file path.
#[clap(long, default_value = "./package.xml")]
target_path: PathBuf,
/// Project directory path.
#[clap(long, default_value = ".")]
project_path: PathBuf,
/// Version of skywalking_agent.
#[clap(long)]
version: String,
/// Release date, default is current local timezone date.
#[clap(long)]
date: Option<String>,
/// Release notes.
#[clap(long)]
notes: String,
}
#[derive(Serialize)]
struct File {
name: String,
role: String,
}
impl File {
fn new(path: &str) -> Self {
let path = path.trim_matches('"');
let role = if path.ends_with(".md")
|| path.starts_with("docs/")
|| path.starts_with("dist-material/")
|| ["LICENSE", "NOTICE"].contains(&path)
{
"doc"
} else {
"src"
};
Self {
name: path.to_owned(),
role: role.to_owned(),
}
}
}
impl CreatePackageXmlCommand {
pub fn run(&self) -> anyhow::Result<()> {
info!(tpl_path = ?&self.tpl_path, "read template content");
let tpl = fs::read_to_string(&self.tpl_path)?;
let mut context = Context::new();
context.insert("date", &self.get_date());
context.insert("version", &self.version);
context.insert("notes", &self.notes);
context.insert("files", &self.get_git_files()?);
let mut tera = Tera::default();
let contents = tera.render_str(&tpl, &context)?;
info!(target_path = ?&self.target_path, "write target content");
fs::write(&self.target_path, contents)?;
Ok(())
}
fn get_date(&self) -> String {
match &self.date {
Some(date) => date.to_owned(),
None => {
let datetime: DateTime<Local> = SystemTime::now().into();
datetime.format("%Y-%m-%d").to_string()
}
}
}
fn get_git_files(&self) -> anyhow::Result<Vec<File>> {
let output = Command::new("git")
.args(["ls-tree", "-r", "HEAD", "--name-only"])
.output()?;
let content = String::from_utf8(output.stdout)?;
Ok(content.split_whitespace().map(File::new).collect())
}
}