44//
55// The full license is in the file LICENSE, distributed with this software.
66
7+ #include < fstream>
78#include < iostream>
89
10+ #include < yaml-cpp/yaml.h>
11+
912#include " mamba/api/configuration.hpp"
1013#include " mamba/api/create.hpp"
1114#include " mamba/api/install.hpp"
@@ -57,6 +60,7 @@ namespace mamba
5760 void clone_environment (
5861 Context& ctx,
5962 ChannelContext& channel_context,
63+ Configuration& config,
6064 const fs::u8path& source_prefix,
6165 bool create_env,
6266 bool remove_prefix_on_failure
@@ -77,40 +81,85 @@ namespace mamba
7781 }
7882 const PrefixData& source_prefix_data = maybe_prefix_data.value ();
7983
80- std::vector<std::string> explicit_urls;
81- const auto records = source_prefix_data.sorted_records ();
82- explicit_urls.reserve (records.size ());
83-
84- for (const auto & pkg : records)
84+ // Export source environment to YAML format
85+ TemporaryFile yaml_file (" mamba_env_" , " .yml" );
8586 {
86- if (pkg.package_url .empty ())
87+ YAML::Emitter out;
88+ out << YAML::BeginMap;
89+
90+ // Add dependencies section
91+ out << YAML::Key << " dependencies" << YAML::Value << YAML::BeginSeq;
92+
93+ // Add conda packages
94+ const auto records = source_prefix_data.sorted_records ();
95+ for (const auto & pkg : records)
8796 {
88- // Fallback to channel/platform/filename if possible.
89- if (pkg.channel .empty () || pkg.platform .empty () || pkg.filename .empty ())
90- {
91- LOG_WARNING << " Skipping package without URL information while cloning: "
92- << pkg.name ;
93- continue ;
94- }
95- const auto url = pkg.url_for_channel (pkg.channel );
96- explicit_urls.push_back (url);
97+ out << fmt::format (" {}={}={}" , pkg.name , pkg.version , pkg.build_string );
9798 }
98- else
99+
100+ // Add pip packages as a sub-map
101+ const auto & pip_records = source_prefix_data.pip_records ();
102+ if (!pip_records.empty ())
99103 {
100- std::string url = pkg.package_url ;
101- if (!pkg.sha256 .empty ())
104+ out << YAML::BeginMap;
105+ out << YAML::Key << " pip" << YAML::Value << YAML::BeginSeq;
106+ for (const auto & [name, pkg] : pip_records)
102107 {
103- url += " #sha256: " + pkg.sha256 ;
108+ out << (pkg. name + " == " + pkg.version ) ;
104109 }
105- else if (!pkg.md5 .empty ())
106- {
107- url += " #" + pkg.md5 ;
108- }
109- explicit_urls.push_back (std::move (url));
110+ out << YAML::EndSeq;
111+ out << YAML::EndMap;
110112 }
113+
114+ out << YAML::EndSeq;
115+ out << YAML::EndMap;
116+
117+ // Write YAML to temporary file
118+ std::ofstream yaml_out = open_ofstream (yaml_file.path ());
119+ yaml_out << out.c_str ();
120+ yaml_out.close ();
111121 }
112122
113- install_explicit_specs (ctx, channel_context, explicit_urls, create_env, remove_prefix_on_failure);
123+ // Read YAML file and populate config
124+ const auto parse_result = detail::read_yaml_file (
125+ ctx,
126+ yaml_file.path ().string (),
127+ ctx.platform ,
128+ ctx.use_uv
129+ );
130+
131+ // Populate config with parsed YAML contents
132+ if (!parse_result.dependencies .empty ())
133+ {
134+ auto & specs = config.at (" specs" ).value <std::vector<std::string>>();
135+ specs.insert (
136+ specs.end (),
137+ parse_result.dependencies .begin (),
138+ parse_result.dependencies .end ()
139+ );
140+ }
141+
142+ if (!parse_result.others_pkg_mgrs_specs .empty ())
143+ {
144+ auto & others_pkg_mgrs_specs = config.at (" others_pkg_mgrs_specs" )
145+ .value <std::vector<detail::other_pkg_mgr_spec>>();
146+ others_pkg_mgrs_specs.insert (
147+ others_pkg_mgrs_specs.end (),
148+ parse_result.others_pkg_mgrs_specs .begin (),
149+ parse_result.others_pkg_mgrs_specs .end ()
150+ );
151+ }
152+
153+ // Install packages from config
154+ const auto & install_specs_vec = config.at (" specs" ).value <std::vector<std::string>>();
155+ install_specs (
156+ ctx,
157+ channel_context,
158+ config,
159+ install_specs_vec,
160+ create_env,
161+ remove_prefix_on_failure
162+ );
114163 }
115164 } // namespace
116165
@@ -239,7 +288,14 @@ namespace mamba
239288 {
240289 const auto clone_value = clone_cfg.value <std::string>();
241290 const auto source_prefix = compute_clone_source_prefix (ctx, clone_value);
242- clone_environment (ctx, channel_context, source_prefix, create_env, remove_prefix_on_failure);
291+ clone_environment (
292+ ctx,
293+ channel_context,
294+ config,
295+ source_prefix,
296+ create_env,
297+ remove_prefix_on_failure
298+ );
243299 return ;
244300 }
245301
0 commit comments