1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use std::{
16 fs::{copy, read_link, remove_dir_all},
17 os::unix::fs::symlink,
18 process::Output,
19 };
20
21 use anyhow::{anyhow, Context, Result};
22 use glob::glob;
23
24 use crate::{
25 copy_dir, crate_type::diff_android_bp, most_recent_version, CompatibleVersionPair, Crate,
26 CrateCollection, Migratable, NameAndVersionMap, PseudoCrate, RepoPath, VersionMatch,
27 };
28
29 static CUSTOMIZATIONS: &'static [&'static str] =
30 &["*.bp", "cargo_embargo.json", "patches", "METADATA", "TEST_MAPPING", "MODULE_LICENSE_*"];
31
32 static SYMLINKS: &'static [&'static str] = &["LICENSE", "NOTICE"];
33
34 impl<'a> CompatibleVersionPair<'a, Crate> {
copy_customizations(&self) -> Result<()>35 pub fn copy_customizations(&self) -> Result<()> {
36 let dest_dir_absolute = self.dest.staging_path().abs();
37 for pattern in CUSTOMIZATIONS {
38 let full_pattern = self.source.path().join(pattern);
39 for entry in glob(
40 full_pattern
41 .abs()
42 .to_str()
43 .ok_or(anyhow!("Failed to convert path {} to str", full_pattern))?,
44 )? {
45 let entry = entry?;
46 let filename = entry
47 .file_name()
48 .context(format!("Failed to get file name for {}", entry.display()))?
49 .to_os_string();
50 if entry.is_dir() {
51 copy_dir(&entry, &dest_dir_absolute.join(filename)).context(format!(
52 "Failed to copy {} to {}",
53 entry.display(),
54 self.dest.staging_path()
55 ))?;
56 } else {
57 let dest_file = dest_dir_absolute.join(&filename);
58 if dest_file.exists() {
59 return Err(anyhow!("Destination file {} exists", dest_file.display()));
60 }
61 copy(&entry, dest_dir_absolute.join(filename)).context(format!(
62 "Failed to copy {} to {}",
63 entry.display(),
64 dest_dir_absolute.display()
65 ))?;
66 }
67 }
68 }
69 for link in SYMLINKS {
70 let src_path = self.source.path().join(link);
71 if src_path.abs().is_symlink() {
72 let dest = read_link(src_path.abs())?;
73 if dest.exists() {
74 return Err(anyhow!(
75 "Can't symlink {} -> {} because destination exists",
76 link,
77 dest.display(),
78 ));
79 }
80 symlink(dest, dest_dir_absolute.join(link))?;
81 }
82 }
83 Ok(())
84 }
diff_android_bps(&self) -> Result<Output>85 pub fn diff_android_bps(&self) -> Result<Output> {
86 diff_android_bp(
87 &self.source.android_bp().rel(),
88 &self.dest.staging_path().join(&"Android.bp").rel(),
89 &self.source.path().root(),
90 )
91 .context("Failed to diff Android.bp".to_string())
92 }
93 }
94
migrate( source_dir: RepoPath, pseudo_crate_dir: RepoPath, ) -> Result<VersionMatch<CrateCollection>>95 pub fn migrate(
96 source_dir: RepoPath,
97 pseudo_crate_dir: RepoPath,
98 ) -> Result<VersionMatch<CrateCollection>> {
99 let mut source = CrateCollection::new(source_dir.root());
100 source.add_from(&source_dir.rel())?;
101 source.map_field_mut().retain(|_nv, krate| krate.is_crates_io());
102
103 let pseudo_crate = PseudoCrate::new(pseudo_crate_dir);
104 if pseudo_crate.get_path().abs().exists() {
105 remove_dir_all(pseudo_crate.get_path().abs())
106 .context(format!("Failed to remove {}", pseudo_crate.get_path()))?;
107 }
108 pseudo_crate.init(
109 source
110 .filter_versions(&most_recent_version)
111 .filter(|(_nv, krate)| krate.is_migration_eligible())
112 .map(|(_nv, krate)| krate),
113 )?;
114
115 let mut dest = CrateCollection::new(source.repo_root());
116 dest.add_from(&pseudo_crate.get_path().join(&"vendor").rel())?;
117
118 let mut version_match = VersionMatch::new(source, dest)?;
119
120 version_match.stage_crates()?;
121 version_match.copy_customizations()?;
122 version_match.apply_patches()?;
123 version_match.generate_android_bps()?;
124 version_match.diff_android_bps()?;
125
126 Ok(version_match)
127 }
128