Skip to content

Commit 4724a73

Browse files
authored
create environment.yml for env (#3)
* create environment.yml for env * dont include local channel name as its not conda compatible
1 parent 6922e10 commit 4724a73

File tree

1 file changed

+59
-14
lines changed

1 file changed

+59
-14
lines changed

src/pack.rs

+59-14
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use futures::{
1515
StreamExt, TryStreamExt,
1616
};
1717
use indicatif::ProgressStyle;
18-
use rattler_conda_types::Platform;
19-
use rattler_lock::{LockFile, Package};
18+
use rattler_conda_types::{PackageRecord, Platform};
19+
use rattler_lock::{CondaPackage, LockFile, Package};
2020
use rattler_networking::{AuthenticationMiddleware, AuthenticationStorage};
2121
use reqwest_middleware::ClientWithMiddleware;
2222
use tokio_tar::Builder;
@@ -65,9 +65,20 @@ pub async fn pack(options: PackOptions) -> Result<()> {
6565
options.platform.as_str()
6666
))?;
6767

68+
let mut conda_packages = Vec::new();
69+
70+
for package in packages {
71+
match package {
72+
Package::Conda(p) => conda_packages.push(p),
73+
Package::Pypi(_) => {
74+
anyhow::bail!("pypi packages are not supported in pixi-pack");
75+
}
76+
}
77+
}
78+
6879
// Download packages to temporary directory.
69-
tracing::info!("Downloading {} packages", packages.len());
70-
let bar = indicatif::ProgressBar::new(packages.len() as u64);
80+
tracing::info!("Downloading {} packages", conda_packages.len());
81+
let bar = indicatif::ProgressBar::new(conda_packages.len() as u64);
7182
bar.set_style(
7283
ProgressStyle::with_template(
7384
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
@@ -81,7 +92,7 @@ pub async fn pack(options: PackOptions) -> Result<()> {
8192

8293
let channel_dir = output_folder.path().join(CHANNEL_DIRECTORY_NAME);
8394

84-
stream::iter(packages)
95+
stream::iter(conda_packages.iter())
8596
.map(Ok)
8697
.try_for_each_concurrent(50, |package| async {
8798
download_package(&client, package, &channel_dir).await?;
@@ -105,6 +116,13 @@ pub async fn pack(options: PackOptions) -> Result<()> {
105116
let metadata = serde_json::to_string_pretty(&options.metadata)?;
106117
metadata_file.write_all(metadata.as_bytes()).await?;
107118

119+
// Create environment file.
120+
create_environment_file(
121+
output_folder.path(),
122+
conda_packages.iter().map(|p| p.package_record()),
123+
)
124+
.await?;
125+
108126
// Pack = archive + compress the contents.
109127
archive_directory(output_folder.path(), &options.output_file, options.level)
110128
.await
@@ -146,25 +164,21 @@ fn reqwest_client_from_auth_storage(auth_file: Option<PathBuf>) -> Result<Client
146164
/// Download a conda package to a given output directory.
147165
async fn download_package(
148166
client: &ClientWithMiddleware,
149-
package: Package,
167+
package: &CondaPackage,
150168
output_dir: &Path,
151169
) -> Result<()> {
152-
let conda_package = package
153-
.as_conda()
154-
.ok_or(anyhow!("package is not a conda package"))?; // TODO: we might want to skip here
155-
156-
let output_dir = output_dir.join(&conda_package.package_record().subdir);
170+
let output_dir = output_dir.join(&package.package_record().subdir);
157171
create_dir_all(&output_dir)
158172
.await
159173
.map_err(|e| anyhow!("could not create download directory: {}", e))?;
160174

161-
let file_name = conda_package
175+
let file_name = package
162176
.file_name()
163177
.ok_or(anyhow!("could not get file name"))?;
164178
let mut dest = File::create(output_dir.join(file_name)).await?;
165179

166-
tracing::debug!("Fetching package {}", conda_package.url());
167-
let mut response = client.get(conda_package.url().to_string()).send().await?;
180+
tracing::debug!("Fetching package {}", package.url());
181+
let mut response = client.get(package.url().to_string()).send().await?;
168182

169183
while let Some(chunk) = response.chunk().await? {
170184
dest.write_all(&chunk).await?;
@@ -211,3 +225,34 @@ async fn archive_directory(
211225

212226
Ok(())
213227
}
228+
229+
async fn create_environment_file(
230+
destination: &Path,
231+
packages: impl IntoIterator<Item = &PackageRecord>,
232+
) -> Result<()> {
233+
let environment_path = destination.join("environment.yml");
234+
235+
let mut environment = String::new();
236+
237+
environment.push_str("channels:\n");
238+
environment.push_str(&format!(" - ./{CHANNEL_DIRECTORY_NAME}\n",));
239+
environment.push_str(" - nodefaults\n");
240+
environment.push_str("dependencies:\n");
241+
242+
for package in packages {
243+
let match_spec_str = format!(
244+
"{}={}={}",
245+
package.name.as_normalized(),
246+
package.version,
247+
package.build,
248+
);
249+
250+
environment.push_str(&format!(" - {}\n", match_spec_str));
251+
}
252+
253+
fs::write(environment_path, environment)
254+
.await
255+
.map_err(|e| anyhow!("Could not write environment file: {}", e))?;
256+
257+
Ok(())
258+
}

0 commit comments

Comments
 (0)