Skip to content

Commit 9188602

Browse files
committed
Support non-virtual workspaces
1 parent 5c3dee5 commit 9188602

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

easybuild/easyblocks/generic/cargo.py

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,19 @@
7777
CARGO_CHECKSUM_JSON = '{{"files": {{}}, "package": "{checksum}"}}'
7878

7979

80-
def get_virtual_workspace_members(crate_dir):
81-
"""Find all members of a cargo virtual workspace in crate_dir.
80+
def get_workspace_members(crate_dir):
81+
"""Find all members of a cargo workspace in crate_dir.
8282
8383
(Minimally) parse the Cargo.toml file.
84-
If it is a virtual workspace ([workspace] and no [package]) return all members (subfolder names).
85-
Otherwise return None.
84+
85+
Return a tuple: (has_package, workspace-members).
86+
has_package determines if the manifest contains a '[package]' section and hence is not a virtual manifest.
87+
workspace-members are all members (subfolder names) if it is a workspace, otherwise None
8688
"""
8789
cargo_toml = os.path.join(crate_dir, 'Cargo.toml')
8890
lines = [line.strip() for line in read_file(cargo_toml).splitlines()]
89-
if '[package]' in lines:
90-
return None
91+
# A virtual (workspace) manifest has no [package], but only a [workspace] section.
92+
has_package = '[package]' in lines
9193

9294
# We are looking for this:
9395
# [workspace]
@@ -100,7 +102,7 @@ def get_virtual_workspace_members(crate_dir):
100102
try:
101103
start_idx = lines.index('[workspace]')
102104
except ValueError:
103-
return None
105+
return has_package, None
104106
# Find "members = [" and concatenate the value, stop at end of section or file
105107
member_str = None
106108
for line in lines[start_idx + 1:]:
@@ -127,7 +129,7 @@ def get_virtual_workspace_members(crate_dir):
127129
if invalid_members:
128130
raise EasyBuildError('Failed to parse %s: Found seemingly invalid members: %s',
129131
cargo_toml, ', '.join(invalid_members))
130-
return members
132+
return has_package, members
131133

132134

133135
def get_checksum(src, log):
@@ -360,13 +362,15 @@ def _setup_offline_config(self, git_sources):
360362
self.log.debug(f'No source found for {crate_dir}. Using nul-checksum for vendoring')
361363
checksum = 'null'
362364
# Sources might contain multiple crates/folders in a so-called "workspace".
363-
# If there isn't a main package (Only "[workspace]" section and no "[package]" section) we have to move
364-
# the individual packages out of the workspace or cargo fails with
365+
# We have to move the individual packages out of the workspace so cargo can find them.
366+
# If there is a main package it should to used too,
367+
# otherwise (Only "[workspace]" section and no "[package]" section)
368+
# we have to remove the top-level folder or cargo fails with:
365369
# "found a virtual manifest at [...]Cargo.toml instead of a package manifest"
366-
member_dirs = get_virtual_workspace_members(crate_dir)
370+
has_package, member_dirs = get_workspace_members(crate_dir)
367371
if member_dirs:
368-
self.log.info(f'Found virtual manifest in {crate_dir}. Members: ' + ', '.join(member_dirs))
369-
crate_dirs = []
372+
self.log.info(f'Found workspace in {crate_dir}. Members: ' + ', '.join(member_dirs))
373+
cargo_pkg_dirs = []
370374
tmp_crate_dir = os.path.join(tmp_dir, os.path.basename(crate_dir))
371375
shutil.move(crate_dir, tmp_crate_dir)
372376
for crate in member_dirs:
@@ -376,13 +380,22 @@ def _setup_offline_config(self, git_sources):
376380
f'as target path {target_path} exists')
377381
# Use copy_dir to resolve symlinks that might point to the parent folder
378382
copy_dir(os.path.join(tmp_crate_dir, crate), target_path, symlinks=False)
379-
crate_dirs.append(target_path)
380-
remove_dir(tmp_crate_dir)
383+
cargo_pkg_dirs.append(target_path)
384+
if has_package:
385+
# Remove the copied crate folders
386+
for crate in member_dirs:
387+
remove_dir(os.path.join(tmp_crate_dir, crate))
388+
# Keep the main package in the original location
389+
shutil.move(tmp_crate_dir, crate_dir)
390+
cargo_pkg_dirs.append(crate_dir)
391+
else:
392+
self.log.info(f'Virtual manifest found in {crate_dir}, removing it')
393+
remove_dir(tmp_crate_dir)
381394
else:
382-
crate_dirs = [crate_dir]
383-
for crate_dir in crate_dirs:
384-
self.log.info('creating .cargo-checksums.json file for %s', os.path.basename(crate_dir))
385-
chkfile = os.path.join(crate_dir, '.cargo-checksum.json')
395+
cargo_pkg_dirs = [crate_dir]
396+
for pkg_dir in cargo_pkg_dirs:
397+
self.log.info('creating .cargo-checksums.json file for %s', os.path.basename(pkg_dir))
398+
chkfile = os.path.join(pkg_dir, '.cargo-checksum.json')
386399
write_file(chkfile, CARGO_CHECKSUM_JSON.format(checksum=checksum))
387400

388401
self.log.debug("Writting config.toml entry for vendored crates from crate.io")

0 commit comments

Comments
 (0)