blob: 17b1a7a2865e895d81c41779d246c7d7ff815341 [file] [log] [blame]
// Copyright (C) 2024 The Android Open Source Project
//
// Licensed 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 std::{
fs::{read_to_string, write},
path::PathBuf,
};
use anyhow::{anyhow, Result};
use chrono::{DateTime, Datelike, Local};
use license_checker::LicenseState;
use name_and_version::NamedAndVersioned;
use crate::{
license::most_restrictive_type,
metadata::{self, Identifier, MetaData},
};
pub struct GoogleMetadata {
path: PathBuf,
metadata: MetaData,
}
impl GoogleMetadata {
pub fn try_from<P: Into<PathBuf>>(path: P) -> Result<Self> {
let path = path.into();
let metadata = read_to_string(&path)?;
let metadata: metadata::MetaData = protobuf::text_format::parse_from_str(&metadata)?;
Ok(GoogleMetadata { path, metadata })
}
pub fn init<P: Into<PathBuf>>(
path: P,
nv: &dyn NamedAndVersioned,
desc: &str,
licenses: &LicenseState,
) -> Result<Self> {
let path = path.into();
if path.exists() {
return Err(anyhow!("{} already exists", path.display()));
}
let mut metadata = GoogleMetadata { path, metadata: MetaData::new() };
metadata.metadata.set_name(nv.name().to_string());
metadata.metadata.set_description(desc.to_string());
metadata.set_date_to_today()?;
metadata.set_identifier(nv)?;
let third_party = metadata.metadata.third_party.mut_or_insert_default();
third_party.set_homepage(nv.crates_io_homepage());
third_party.set_license_type(most_restrictive_type(licenses));
Ok(metadata)
}
pub fn write(&self) -> Result<()> {
Ok(write(&self.path, protobuf::text_format::print_to_string_pretty(&self.metadata))?)
}
pub fn set_date_to_today(&mut self) -> Result<()> {
let now: DateTime<Local> = Local::now();
let date = self
.metadata
.third_party
.mut_or_insert_default()
.last_upgrade_date
.mut_or_insert_default();
date.set_day(now.day().try_into()?);
date.set_month(now.month().try_into()?);
date.set_year(now.year());
Ok(())
}
pub fn set_identifier(&mut self, nv: &dyn NamedAndVersioned) -> Result<()> {
if self.metadata.name.as_ref().ok_or(anyhow!("No name"))? != nv.name() {
return Err(anyhow!("Names don't match"));
}
let mut identifier = Identifier::new();
identifier.set_type("Archive".to_string());
identifier.set_value(nv.crate_archive_url());
identifier.set_version(nv.version().to_string());
self.metadata.third_party.mut_or_insert_default().identifier.clear();
self.metadata.third_party.mut_or_insert_default().identifier.push(identifier);
Ok(())
}
pub fn migrate_homepage(&mut self) -> bool {
let mut homepage = None;
for (idx, identifier) in self.metadata.third_party.identifier.iter().enumerate() {
if identifier.type_.as_ref().unwrap_or(&String::new()).to_lowercase() == "homepage" {
match homepage {
Some(info) => panic!("Homepage set twice? {info:?} {identifier:?}"),
None => homepage = Some((idx, identifier.clone())),
}
}
}
let Some(homepage) = homepage else { return false };
self.metadata.third_party.mut_or_insert_default().identifier.remove(homepage.0);
self.metadata.third_party.mut_or_insert_default().homepage = homepage.1.value;
true
}
pub fn migrate_archive(&mut self) -> bool {
let mut updated = false;
for identifier in self.metadata.third_party.mut_or_insert_default().identifier.iter_mut() {
if identifier.type_ == Some("ARCHIVE".to_string()) {
identifier.type_ = Some("Archive".to_string());
updated = true;
}
}
updated
}
}