Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Spack
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
eic_tools
Spack
Commits
82946d29
Commit
82946d29
authored
10 years ago
by
Todd Gamblin
Browse files
Options
Downloads
Patches
Plain Diff
Move symlink tree routines to LinkTree class.
parent
99775434
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
lib/spack/llnl/util/filesystem.py
+1
-81
1 addition, 81 deletions
lib/spack/llnl/util/filesystem.py
lib/spack/llnl/util/link_tree.py
+168
-0
168 additions, 0 deletions
lib/spack/llnl/util/link_tree.py
lib/spack/spack/package.py
+7
-9
7 additions, 9 deletions
lib/spack/spack/package.py
with
176 additions
and
90 deletions
lib/spack/llnl/util/filesystem.py
+
1
−
81
View file @
82946d29
...
@@ -24,8 +24,7 @@
...
@@ -24,8 +24,7 @@
##############################################################################
##############################################################################
__all__
=
[
'
set_install_permissions
'
,
'
install
'
,
'
expand_user
'
,
'
working_dir
'
,
__all__
=
[
'
set_install_permissions
'
,
'
install
'
,
'
expand_user
'
,
'
working_dir
'
,
'
touch
'
,
'
mkdirp
'
,
'
force_remove
'
,
'
join_path
'
,
'
ancestor
'
,
'
touch
'
,
'
mkdirp
'
,
'
force_remove
'
,
'
join_path
'
,
'
ancestor
'
,
'
can_access
'
,
'
filter_file
'
,
'
change_sed_delimiter
'
,
'
is_exe
'
,
'
can_access
'
,
'
filter_file
'
,
'
change_sed_delimiter
'
,
'
is_exe
'
]
'
check_link_tree
'
,
'
merge_link_tree
'
,
'
unmerge_link_tree
'
]
import
os
import
os
import
sys
import
sys
...
@@ -223,82 +222,3 @@ def ancestor(dir, n=1):
...
@@ -223,82 +222,3 @@ def ancestor(dir, n=1):
def
can_access
(
file_name
):
def
can_access
(
file_name
):
"""
True if we have read/write access to the file.
"""
"""
True if we have read/write access to the file.
"""
return
os
.
access
(
file_name
,
os
.
R_OK
|
os
.
W_OK
)
return
os
.
access
(
file_name
,
os
.
R_OK
|
os
.
W_OK
)
def
traverse_link_tree
(
src_root
,
dest_root
,
follow_nonexisting
=
True
,
**
kwargs
):
# Yield directories before or after their contents.
order
=
kwargs
.
get
(
'
order
'
,
'
pre
'
)
if
order
not
in
(
'
pre
'
,
'
post
'
):
raise
ValueError
(
"
Order must be
'
pre
'
or
'
post
'
.
"
)
# List of relative paths to ignore under the src root.
ignore
=
kwargs
.
get
(
'
ignore
'
,
None
)
if
isinstance
(
ignore
,
basestring
):
ignore
=
(
ignore
,)
for
dirpath
,
dirnames
,
filenames
in
os
.
walk
(
src_root
):
rel_path
=
dirpath
[
len
(
src_root
):]
rel_path
=
rel_path
.
lstrip
(
os
.
path
.
sep
)
dest_dirpath
=
os
.
path
.
join
(
dest_root
,
rel_path
)
# Don't descend into ignored directories
if
ignore
and
dest_dirpath
in
ignore
:
return
# Don't descend into dirs in dest that do not exist in src.
if
not
follow_nonexisting
:
dirnames
[:]
=
[
d
for
d
in
dirnames
if
os
.
path
.
exists
(
os
.
path
.
join
(
dest_dirpath
,
d
))]
# preorder yields directories before children
if
order
==
'
pre
'
:
yield
(
dirpath
,
dest_dirpath
)
for
name
in
filenames
:
src_file
=
os
.
path
.
join
(
dirpath
,
name
)
dest_file
=
os
.
path
.
join
(
dest_dirpath
,
name
)
# Ignore particular paths inside the install root.
src_relpath
=
src_file
[
len
(
src_root
):]
src_relpath
=
src_relpath
.
lstrip
(
os
.
path
.
sep
)
if
ignore
and
src_relpath
in
ignore
:
continue
yield
(
src_file
,
dest_file
)
# postorder yields directories after children
if
order
==
'
post
'
:
yield
(
dirpath
,
dest_dirpath
)
def
check_link_tree
(
src_root
,
dest_root
,
**
kwargs
):
for
src
,
dest
in
traverse_link_tree
(
src_root
,
dest_root
,
False
,
**
kwargs
):
if
os
.
path
.
exists
(
dest
)
and
not
os
.
path
.
isdir
(
dest
):
return
dest
return
None
def
merge_link_tree
(
src_root
,
dest_root
,
**
kwargs
):
kwargs
[
'
order
'
]
=
'
pre
'
for
src
,
dest
in
traverse_link_tree
(
src_root
,
dest_root
,
**
kwargs
):
if
os
.
path
.
isdir
(
src
):
mkdirp
(
dest
)
else
:
assert
(
not
os
.
path
.
exists
(
dest
))
os
.
symlink
(
src
,
dest
)
def
unmerge_link_tree
(
src_root
,
dest_root
,
**
kwargs
):
kwargs
[
'
order
'
]
=
'
post
'
for
src
,
dest
in
traverse_link_tree
(
src_root
,
dest_root
,
**
kwargs
):
if
os
.
path
.
isdir
(
dest
):
if
not
os
.
listdir
(
dest
):
# TODO: what if empty directories were present pre-merge?
shutil
.
rmtree
(
dest
,
ignore_errors
=
True
)
elif
os
.
path
.
exists
(
dest
):
if
not
os
.
path
.
islink
(
dest
):
raise
ValueError
(
"
%s is not a link tree!
"
%
dest
)
os
.
remove
(
dest
)
This diff is collapsed.
Click to expand it.
lib/spack/llnl/util/link_tree.py
0 → 100644
+
168
−
0
View file @
82946d29
##############################################################################
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
#
# This file is part of Spack.
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
# LLNL-CODE-647188
#
# For details, see https://scalability-llnl.github.io/spack
# Please also see the LICENSE file for our notice and the LGPL.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (as published by
# the Free Software Foundation) version 2.1 dated February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
# conditions of the GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
"""
LinkTree class for setting up trees of symbolic links.
"""
__all__
=
[
'
LinkTree
'
]
import
os
import
shutil
from
llnl.util.filesystem
import
mkdirp
class
LinkTree
(
object
):
"""
Class to create trees of symbolic links from a source directory.
LinkTree objects are constructed with a source root. Their
methods allow you to create and delete trees of symbolic links
back to the source tree in specific destination directories.
Trees comprise symlinks only to files; directries are never
symlinked to, to prevent the source directory from ever being
modified.
"""
def
__init__
(
self
,
source_root
):
self
.
_root
=
source_root
def
traverse
(
self
,
dest_root
,
**
kwargs
):
"""
Traverse LinkTree root and dest simultaneously.
Walks the LinkTree directory in pre or post order. Yields
each file in the source directory with a matching path from
the dest directory. e.g., for this tree::
root/
a/
file1
file2
b/
file3
When called on dest, this yields::
(
'
root
'
,
'
dest
'
)
(
'
root/a
'
,
'
dest/a
'
)
(
'
root/a/file1
'
,
'
dest/a/file1
'
)
(
'
root/a/file2
'
,
'
dest/a/file2
'
)
(
'
root/b
'
,
'
dest/b
'
)
(
'
root/b/file3
'
,
'
dest/b/file3
'
)
Optional args:
order=[pre|post] -- Whether to do pre- or post-order traveral.
ignore=<container> -- Optional container of root-relative
paths to ignore.
follow_nonexisting -- Whether to descend into directories in
src that do not exit in dest.
"""
# Yield directories before or after their contents.
order
=
kwargs
.
get
(
'
order
'
,
'
pre
'
)
if
order
not
in
(
'
pre
'
,
'
post
'
):
raise
ValueError
(
"
Order must be
'
pre
'
or
'
post
'
.
"
)
# List of relative paths to ignore under the src root.
ignore
=
kwargs
.
get
(
'
ignore
'
,
None
)
if
isinstance
(
ignore
,
basestring
):
ignore
=
(
ignore
,)
# Whether to descend when dirs dont' exist in dest.
follow_nonexisting
=
kwargs
.
get
(
'
follow_nonexisting
'
,
True
)
for
dirpath
,
dirnames
,
filenames
in
os
.
walk
(
self
.
_root
):
rel_path
=
dirpath
[
len
(
self
.
_root
):]
rel_path
=
rel_path
.
lstrip
(
os
.
path
.
sep
)
dest_dirpath
=
os
.
path
.
join
(
dest_root
,
rel_path
)
# Don't descend into ignored directories
if
ignore
and
dest_dirpath
in
ignore
:
return
# Don't descend into dirs in dest that do not exist in src.
if
not
follow_nonexisting
:
dirnames
[:]
=
[
d
for
d
in
dirnames
if
os
.
path
.
exists
(
os
.
path
.
join
(
dest_dirpath
,
d
))]
# preorder yields directories before children
if
order
==
'
pre
'
:
yield
(
dirpath
,
dest_dirpath
)
for
name
in
filenames
:
src_file
=
os
.
path
.
join
(
dirpath
,
name
)
dest_file
=
os
.
path
.
join
(
dest_dirpath
,
name
)
# Ignore particular paths inside the install root.
src_relpath
=
src_file
[
len
(
self
.
_root
):]
src_relpath
=
src_relpath
.
lstrip
(
os
.
path
.
sep
)
if
ignore
and
src_relpath
in
ignore
:
continue
yield
(
src_file
,
dest_file
)
# postorder yields directories after children
if
order
==
'
post
'
:
yield
(
dirpath
,
dest_dirpath
)
def
find_conflict
(
self
,
dest_root
,
**
kwargs
):
"""
Returns the first file in dest that also exists in src.
"""
kwargs
[
'
follow_nonexisting
'
]
=
False
for
src
,
dest
in
self
.
traverse
(
dest_root
,
**
kwargs
):
if
os
.
path
.
exists
(
dest
)
and
not
os
.
path
.
isdir
(
dest
):
return
dest
return
None
def
merge
(
self
,
dest_root
,
**
kwargs
):
"""
Link all files in src into dest, creating directories if necessary.
"""
kwargs
[
'
order
'
]
=
'
pre
'
for
src
,
dest
in
self
.
traverse
(
dest_root
,
**
kwargs
):
if
os
.
path
.
isdir
(
src
):
mkdirp
(
dest
)
else
:
assert
(
not
os
.
path
.
exists
(
dest
))
os
.
symlink
(
src
,
dest
)
def
unmerge
(
self
,
dest_root
,
**
kwargs
):
"""
Unlink all files in dest that exist in src.
Unlinks directories in dest if they are empty.
"""
kwargs
[
'
order
'
]
=
'
post
'
for
src
,
dest
in
self
.
traverse
(
dest_root
,
**
kwargs
):
if
os
.
path
.
isdir
(
dest
):
if
not
os
.
listdir
(
dest
):
# TODO: what if empty directories were present pre-merge?
shutil
.
rmtree
(
dest
,
ignore_errors
=
True
)
elif
os
.
path
.
exists
(
dest
):
if
not
os
.
path
.
islink
(
dest
):
raise
ValueError
(
"
%s is not a link tree!
"
%
dest
)
os
.
remove
(
dest
)
This diff is collapsed.
Click to expand it.
lib/spack/spack/package.py
+
7
−
9
View file @
82946d29
...
@@ -45,6 +45,7 @@
...
@@ -45,6 +45,7 @@
from
StringIO
import
StringIO
from
StringIO
import
StringIO
import
llnl.util.tty
as
tty
import
llnl.util.tty
as
tty
from
llnl.util.link_tree
import
LinkTree
from
llnl.util.filesystem
import
*
from
llnl.util.filesystem
import
*
from
llnl.util.lang
import
*
from
llnl.util.lang
import
*
...
@@ -918,15 +919,12 @@ def activate(self, extension):
...
@@ -918,15 +919,12 @@ def activate(self, extension):
always executed.
always executed.
"""
"""
conflict
=
check_link_tree
(
tree
=
LinkTree
(
extension
.
prefix
)
extension
.
prefix
,
self
.
prefix
,
conflict
=
tree
.
find_conflict
(
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
self
.
prefix
,
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
if
conflict
:
if
conflict
:
raise
ExtensionConflictError
(
conflict
)
raise
ExtensionConflictError
(
conflict
)
tree
.
merge
(
self
.
prefix
,
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
merge_link_tree
(
extension
.
prefix
,
self
.
prefix
,
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
def
do_deactivate
(
self
,
extension
):
def
do_deactivate
(
self
,
extension
):
...
@@ -950,8 +948,8 @@ def deactivate(self, extension):
...
@@ -950,8 +948,8 @@ def deactivate(self, extension):
always executed.
always executed.
"""
"""
unmerge_l
ink
_t
ree
(
extension
.
prefix
,
self
.
prefix
,
tree
=
L
ink
T
ree
(
extension
.
prefix
)
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
tree
.
unmerge
(
self
.
prefix
,
ignore
=
spack
.
install_layout
.
hidden_file_paths
)
tty
.
msg
(
"
Deactivated %s as extension of %s.
"
tty
.
msg
(
"
Deactivated %s as extension of %s.
"
%
(
extension
.
spec
.
short_spec
,
self
.
spec
.
short_spec
))
%
(
extension
.
spec
.
short_spec
,
self
.
spec
.
short_spec
))
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment