auto 功能初步实现
Signed-off-by: Jia Chao <jiac13@chinaunicom.cn>
This commit is contained in:
parent
6a75014e83
commit
f65a0c3182
|
@ -10,3 +10,5 @@ clap = { version = "4.0", features = ["derive"] }
|
|||
cvrf-xmlparser = { git = "https://git.zhgsun.com:8089/jiachao2130/cvrf-xmlparser.git", version = "0.1.0" }
|
||||
serde = { version = "1", features = ["serde_derive"] }
|
||||
serde_json = { version = "1.0" }
|
||||
tracing = { version = "0.1" }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "local-time"] }
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::Path;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// cvrf2cusa 自动化执行所需的配置
|
||||
|
@ -11,17 +13,28 @@ pub(crate) struct AutoConfig {
|
|||
}
|
||||
|
||||
impl AutoConfig {
|
||||
pub fn from(path: &str) -> crate::Result<Self> {
|
||||
// 从文件中读取配置
|
||||
pub fn from<P: AsRef<Path>>(path: P) -> crate::Result<Self> {
|
||||
let data = std::fs::read_to_string(path)?;
|
||||
|
||||
Ok(serde_json::from_str::<Self>(&data)?)
|
||||
}
|
||||
|
||||
// 获取 source 字段
|
||||
pub fn source(&self) -> &str {
|
||||
&self.source
|
||||
}
|
||||
|
||||
// 获取 target 字段
|
||||
pub fn target(&self) -> &str {
|
||||
&self.target
|
||||
}
|
||||
}
|
||||
|
||||
/// cuvars 中,关于源码追踪,自动修复相关的配置项,一般位于组件最底层的目录,`config.json`
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub(crate) struct RepairConfig {
|
||||
// 对应了 openEuelr 的上游版本
|
||||
// 对应了 openEuelr 的上游版本, 例 22.03-LST,不可包含 openEuler 字段
|
||||
upstream: String,
|
||||
|
||||
// 此组件是否支持自动修复
|
||||
|
@ -31,9 +44,18 @@ pub(crate) struct RepairConfig {
|
|||
fixed_version: String,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl RepairConfig {
|
||||
pub fn new(upstream: String, autobuild: bool, fixed_version: String) -> Self {
|
||||
RepairConfig {
|
||||
upstream,
|
||||
autobuild,
|
||||
fixed_version
|
||||
}
|
||||
}
|
||||
|
||||
/// 从指定的路径读取文件并将之转换为 `RepairConfig`
|
||||
pub fn read(path: &str) -> crate::Result<Self> {
|
||||
pub fn from<P: AsRef<Path>>(path: P) -> crate::Result<Self> {
|
||||
let data = std::fs::read_to_string(path)?;
|
||||
|
||||
Ok(serde_json::from_str::<Self>(&data)?)
|
||||
|
|
127
src/lib.rs
127
src/lib.rs
|
@ -3,6 +3,10 @@ use std::fs;
|
|||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tracing_subscriber::{fmt, EnvFilter};
|
||||
use tracing::{trace, debug, info, error};
|
||||
|
||||
use config::RepairConfig;
|
||||
use cvrf_xmlparser::{
|
||||
CVRF,
|
||||
// SaInfo 即为 CUSA
|
||||
|
@ -21,6 +25,7 @@ pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
|||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub fn cumain() -> Result<()> {
|
||||
set_up_logging()?;
|
||||
let cli = cli::parse();
|
||||
|
||||
match cli.subcommand {
|
||||
|
@ -30,6 +35,15 @@ pub fn cumain() -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_up_logging() -> crate::Result<()> {
|
||||
fmt()
|
||||
.with_ansi(false)
|
||||
.with_timer(fmt::time::OffsetTime::local_rfc_3339().unwrap())
|
||||
.with_line_number(true)
|
||||
.with_env_filter(EnvFilter::from_default_env())
|
||||
.try_init()
|
||||
}
|
||||
|
||||
/// 可使用 convert 函数将 cvrf 格式文件转换并输出至指定的 cusa 文件。
|
||||
///
|
||||
/// 例:
|
||||
|
@ -178,9 +192,120 @@ pub fn auto() -> Result<()> {
|
|||
"cvrf2cusa.json"
|
||||
}
|
||||
};
|
||||
info!("Config file is: {}", config);
|
||||
|
||||
let auto = config::AutoConfig::from(config)?;
|
||||
info!("Load AutoConfig: {:?}", auto);
|
||||
|
||||
let files = walk_dir(auto.source(), true);
|
||||
|
||||
for _file in files {
|
||||
match _file.extension() {
|
||||
Some(tail) => {
|
||||
if tail != "xml" {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 从 xml 中读取 cvrf 并转换为 cusa
|
||||
let file = if let Some(file) = _file.to_str() {
|
||||
file
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
trace!("parsing {}", file);
|
||||
let mut cvrf = CVRF::new();
|
||||
let _ = cvrf.load_xml(file);
|
||||
|
||||
_save_2_cusa_db(auto.target(), &cvrf)?;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn _save_2_cusa_db(dbpath: &str, cvrf: &CVRF) -> Result<()> {
|
||||
let mut db = PathBuf::from(dbpath);
|
||||
|
||||
let component = cvrf.affected_component().unwrap();
|
||||
trace!("Get affected_component: {}", component);
|
||||
// 这里随便取一个 src 包名
|
||||
let _src = cvrf.producttree.packages["src"][0].productid.as_str();
|
||||
|
||||
// TODO: may empty
|
||||
if _src == "" {
|
||||
error!("{}: ProductTree->packages[\"src\"] have empty productid, ignore it!", cvrf.id());
|
||||
return Ok(())
|
||||
}
|
||||
db.push(_src.chars().next().unwrap().to_string());
|
||||
// TODO!()
|
||||
// db: "cusas/l/log4j,mybatis,netty,springframework,wildfly-security-manager,wildfly-elytron,wildfly-build-tools,wildfly-common,wildfly-core,thrift,json-lib,datanucleus-core,jgroups,mx4j,jboss-logging,infinispan,datanucleus-rdbms,avalon-logkit,datanucleus-api-jdo,avalon-framework,HikariCP,metrics"
|
||||
// Error: Os { code: 63, kind: InvalidFilename, message: "File name too long" }
|
||||
db.push(component);
|
||||
|
||||
// 读取修复配置
|
||||
let mut repairconf = db.clone();
|
||||
repairconf.push("config.json");
|
||||
let repairconfig = match config::RepairConfig::from(&repairconf) {
|
||||
Ok(repairconfig) => repairconfig,
|
||||
_ => {
|
||||
// 这里临时处理下,不应该创建
|
||||
// TO BE DELETE
|
||||
let parent = repairconf.parent().unwrap();
|
||||
match fs::create_dir_all(parent) {
|
||||
Ok(_) => {},
|
||||
Err(e) => {
|
||||
error!("sa_id: {}, {}", cvrf.id(), e.to_string());
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
let repairconfig = RepairConfig::new(
|
||||
"22.03-LTS".to_string(),
|
||||
true,
|
||||
"".to_string(),
|
||||
);
|
||||
// 写入默认配置
|
||||
let data = serde_json::to_string_pretty(&repairconfig)?;
|
||||
let mut repair = fs::OpenOptions::new().read(true).write(true).create(true).open(repairconf)?;
|
||||
repair.write(data.as_bytes())?;
|
||||
repair.flush()?;
|
||||
|
||||
repairconfig
|
||||
}
|
||||
};
|
||||
|
||||
// 是否影响当前软件包,即作上游判断
|
||||
let mut not_affected = true;
|
||||
for product in cvrf.affected_products() {
|
||||
if product.productid.ends_with(repairconfig.upstream()) {
|
||||
not_affected = false;
|
||||
}
|
||||
}
|
||||
if not_affected {
|
||||
debug!("{} not effected {}'s {}, skip...", cvrf.id(), repairconfig.upstream(), component);
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
// 增加 sa 信息
|
||||
let mut nvr = String::new();
|
||||
for product in &cvrf.producttree.packages["src"] {
|
||||
if product.cpe.ends_with(repairconfig.upstream()) {
|
||||
nvr = product.productid.clone();
|
||||
nvr.push_str(&format!("_{}.json", cvrf.id()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
db.push(&nvr);
|
||||
|
||||
if db.exists() {
|
||||
debug!("{} is already converted!", cvrf.id());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let data = serde_json::to_string_pretty(&cvrf.sainfo())?;
|
||||
let mut sa_file = fs::OpenOptions::new().read(true).write(true).create(true).open(db)?;
|
||||
sa_file.write(data.as_bytes())?;
|
||||
sa_file.flush()?;
|
||||
|
||||
todo!();
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user