Skip to content

Commit

Permalink
sources: fix workdir in ignore patterns
Browse files Browse the repository at this point in the history
If workdir matches source dir, ignore parts/stage/prime. Otherwise
verify if workdir is inside sourcedir, and ignore it if this is
the case.

Signed-off-by: Claudio Matsuoka <[email protected]>
  • Loading branch information
cmatsuoka committed Jul 19, 2021
1 parent 9fd6ee7 commit 39c0119
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 21 deletions.
7 changes: 5 additions & 2 deletions craft_parts/sources/local_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,16 @@ def __init__(self, *args, copy_function=file_utils.link_or_copy, **kwargs):
self.source_abspath = os.path.abspath(self.source)
self.copy_function = copy_function

if self._dirs.work_dir.resolve() == Path.cwd():
if self._dirs.work_dir.resolve() == Path(self.source_abspath):
# ignore parts/stage/dir if source dir matches workdir
self._ignore_patterns.append(self._dirs.parts_dir.name)
self._ignore_patterns.append(self._dirs.stage_dir.name)
self._ignore_patterns.append(self._dirs.prime_dir.name)
else:
# otherwise check if work_dir inside source dir
with contextlib.suppress(ValueError):
rel_work_dir = self._dirs.work_dir.relative_to(Path.cwd())
rel_work_dir = self._dirs.work_dir.relative_to(self.source_abspath)
# deep workdirs will be cut at the first component
self._ignore_patterns.append(rel_work_dir.parts[0])

logger.debug("ignore patterns: %r", self._ignore_patterns)
Expand Down
99 changes: 80 additions & 19 deletions tests/unit/sources/test_local_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,36 +101,33 @@ def test_pulling_twice_with_existing_source_dir_recreates_hardlinks(self, new_di

def test_pull_ignores_own_work_data(self, new_dir):
# Make the snapcraft-specific directories
os.makedirs(os.path.join("src", "parts"))
os.makedirs(os.path.join("src", "stage"))
os.makedirs(os.path.join("src", "prime"))
os.makedirs(os.path.join("src", "other"))
os.makedirs("parts/foo/src")
os.makedirs("stage")
os.makedirs("prime")
os.makedirs("other")

# Create an application-specific file
open(os.path.join("src", "foo.znap"), "w").close()
open("foo.znap", "w").close()

# Now make some real files
os.makedirs(os.path.join("src", "dir"))
open(os.path.join("src", "dir", "file"), "w").close()

os.mkdir("destination")
os.makedirs("dir")
open(os.path.join("dir", "file"), "w").close()

local = LocalSource(
"src", "destination", cache_dir=new_dir, ignore_patterns=["*.znap"]
".", "parts/foo/src", cache_dir=new_dir, ignore_patterns=["*.znap"]
)
local.pull()

# Verify that the work directories got filtered out
assert os.path.isdir(os.path.join("destination", "parts")) is False
assert os.path.isdir(os.path.join("destination", "stage")) is False
assert os.path.isdir(os.path.join("destination", "prime")) is False
assert os.path.isdir(os.path.join("destination", "other"))
assert os.path.isfile(os.path.join("destination", "foo.znap")) is False
assert os.path.isdir(os.path.join("parts", "foo", "src", "parts")) is False
assert os.path.isdir(os.path.join("parts", "foo", "src", "stage")) is False
assert os.path.isdir(os.path.join("parts", "foo", "src", "prime")) is False
assert os.path.isdir(os.path.join("parts", "foo", "src", "other"))
assert os.path.isfile(os.path.join("parts", "foo", "src", "foo.znap")) is False

# Verify that the real stuff made it in.
assert os.path.islink("destination") is False
assert os.path.islink(os.path.join("destination", "dir")) is False
assert os.stat(os.path.join("destination", "dir", "file")).st_nlink > 1
assert os.path.isdir(os.path.join("parts", "foo", "src", "dir"))
assert os.stat(os.path.join("parts", "foo", "src", "dir", "file")).st_nlink > 1

def test_pull_ignores_own_work_data_work_dir(self, new_dir):
# Make the snapcraft-specific directories
Expand All @@ -139,10 +136,11 @@ def test_pull_ignores_own_work_data_work_dir(self, new_dir):
os.makedirs(os.path.join("src", "stage"))
os.makedirs(os.path.join("src", "prime"))
os.makedirs(os.path.join("src", "other"))
open(os.path.join("src", "foo.znap"), "w").close()

os.mkdir("destination")

dirs = ProjectDirs(work_dir="work_dir")
dirs = ProjectDirs(work_dir="src/work_dir")
local = LocalSource(
"src",
"destination",
Expand All @@ -154,13 +152,76 @@ def test_pull_ignores_own_work_data_work_dir(self, new_dir):

# Verify that the work directories got filtered out
assert os.path.isdir(os.path.join("destination", "work_dir")) is False
assert os.path.isdir(os.path.join("destination", "foo.znap")) is False
assert os.path.isdir(os.path.join("destination", "other"))

# These are now allowed since we have set work_dir
assert os.path.isdir(os.path.join("destination", "parts"))
assert os.path.isdir(os.path.join("destination", "stage"))
assert os.path.isdir(os.path.join("destination", "prime"))

def test_pull_ignores_own_work_data_deep_work_dir(self, new_dir):
# Make the snapcraft-specific directories
os.makedirs(os.path.join("src", "some/deep/work_dir"))
os.makedirs(os.path.join("src", "parts"))
os.makedirs(os.path.join("src", "stage"))
os.makedirs(os.path.join("src", "prime"))
os.makedirs(os.path.join("src", "other"))
os.makedirs(os.path.join("src", "work_dir"))
open(os.path.join("src", "foo.znap"), "w").close()

os.mkdir("destination")

dirs = ProjectDirs(work_dir="src/some/deep/work_dir")
local = LocalSource(
"src",
"destination",
cache_dir=new_dir,
project_dirs=dirs,
ignore_patterns=["*.znap"],
)
local.pull()

# Verify that the work directories got filtered out
assert os.path.isdir(os.path.join("destination", "some/deep/work_dir")) is False
assert os.path.isdir(os.path.join("destination", "foo.znap")) is False
assert os.path.isdir(os.path.join("destination", "other"))

# These are now allowed since we have set work_dir
assert os.path.isdir(os.path.join("destination", "parts"))
assert os.path.isdir(os.path.join("destination", "stage"))
assert os.path.isdir(os.path.join("destination", "prime"))

# This has the same name but it's not the real work dir
assert os.path.isdir(os.path.join("destination", "work_dir"))

def test_pull_work_dir_outside(self, new_dir):
# Make the snapcraft-specific directories
os.makedirs(os.path.join("src", "work_dir"))
os.makedirs(os.path.join("src", "parts"))
os.makedirs(os.path.join("src", "stage"))
os.makedirs(os.path.join("src", "prime"))
os.makedirs(os.path.join("src", "other"))

os.mkdir("destination")

dirs = ProjectDirs(work_dir="/work_dir")
local = LocalSource(
"src",
"destination",
cache_dir=new_dir,
project_dirs=dirs,
ignore_patterns=["*.znap"],
)
local.pull()

# These are all allowed since work_dir is located outside
assert os.path.isdir(os.path.join("destination", "work_dir"))
assert os.path.isdir(os.path.join("destination", "other"))
assert os.path.isdir(os.path.join("destination", "parts"))
assert os.path.isdir(os.path.join("destination", "stage"))
assert os.path.isdir(os.path.join("destination", "prime"))

def test_pull_keeps_symlinks(self, new_dir):
# Create a source containing a directory, a file and symlinks to both.
os.makedirs(os.path.join("src", "dir"))
Expand Down

0 comments on commit 39c0119

Please sign in to comment.