Skip to content

Commit

Permalink
feat: Write CACHEDIR.TAG file (#2805)
Browse files Browse the repository at this point in the history
Signed-off-by: Bernát Gábor <[email protected]>
Co-authored-by: Neil Ramsay <[email protected]>
Co-authored-by: Bernát Gábor <[email protected]>
  • Loading branch information
3 people authored Nov 26, 2024
1 parent d619967 commit 2a29a1b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/changelog/2803.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Write CACHEDIR.TAG file on creation - by "user:`neilramsay`.
14 changes: 14 additions & 0 deletions src/virtualenv/create/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import os
import sys
import textwrap
from abc import ABC, abstractmethod
from argparse import ArgumentTypeError
from ast import literal_eval
Expand Down Expand Up @@ -157,10 +158,23 @@ def run(self):
LOGGER.debug("delete %s", self.dest)
safe_delete(self.dest)
self.create()
self.add_cachedir_tag()
self.set_pyenv_cfg()
if not self.no_vcs_ignore:
self.setup_ignore_vcs()

def add_cachedir_tag(self):
"""Generate a file indicating that this is not meant to be backed up."""
cachedir_tag_file = self.dest / "CACHEDIR.TAG"
if not cachedir_tag_file.exists():
cachedir_tag_text = textwrap.dedent("""
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Python virtualenv.
# For information about cache directory tags, see:
# https://bford.info/cachedir/
""").strip()
cachedir_tag_file.write_text(cachedir_tag_text, encoding="utf-8")

def set_pyenv_cfg(self):
self.pyenv_cfg.content = OrderedDict()
self.pyenv_cfg["home"] = os.path.dirname(os.path.abspath(self.interpreter.system_executable))
Expand Down
32 changes: 32 additions & 0 deletions tests/integration/test_cachedir_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from __future__ import annotations

import shutil
import sys
from subprocess import check_output, run
from typing import TYPE_CHECKING

import pytest

from virtualenv import cli_run

if TYPE_CHECKING:
from pathlib import Path

# gtar => gnu-tar on macOS
TAR = next((target for target in ("gtar", "tar") if shutil.which(target)), None)


def compatible_is_tar_present() -> bool:
return TAR and "--exclude-caches" in check_output(args=[TAR, "--help"], text=True)


@pytest.mark.skipif(sys.platform == "win32", reason="Windows does not have tar")
@pytest.mark.skipif(not compatible_is_tar_present(), reason="Compatible tar is not installed")
def test_cachedir_tag_ignored_by_tag(tmp_path: Path) -> None:
venv = tmp_path / ".venv"
cli_run(["--activators", "", "--without-pip", str(venv)])

args = [TAR, "--create", "--file", "/dev/null", "--exclude-caches", "--verbose", venv.name]
tar_result = run(args=args, capture_output=True, text=True, cwd=tmp_path)
assert tar_result.stdout == ".venv/\n.venv/CACHEDIR.TAG\n"
assert tar_result.stderr == f"{TAR}: .venv/: contains a cache directory tag CACHEDIR.TAG; contents not dumped\n"
28 changes: 28 additions & 0 deletions tests/unit/create/test_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import stat
import subprocess
import sys
import textwrap
import zipfile
from collections import OrderedDict
from itertools import product
Expand Down Expand Up @@ -223,6 +224,33 @@ def list_to_str(iterable):
assert git_ignore.splitlines() == [comment, "*"]


def test_create_cachedir_tag(tmp_path):
cachedir_tag_file = tmp_path / "CACHEDIR.TAG"
cli_run([str(tmp_path), "--without-pip", "--activators", ""])

expected = """
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by Python virtualenv.
# For information about cache directory tags, see:
# https://bford.info/cachedir/
"""
assert cachedir_tag_file.read_text(encoding="utf-8") == textwrap.dedent(expected).strip()


def test_create_cachedir_tag_exists(tmp_path: Path) -> None:
cachedir_tag_file = tmp_path / "CACHEDIR.TAG"
cachedir_tag_file.write_text("magic", encoding="utf-8")
cli_run([str(tmp_path), "--without-pip", "--activators", ""])
assert cachedir_tag_file.read_text(encoding="utf-8") == "magic"


def test_create_cachedir_tag_exists_override(tmp_path: Path) -> None:
cachedir_tag_file = tmp_path / "CACHEDIR.TAG"
cachedir_tag_file.write_text("magic", encoding="utf-8")
cli_run([str(tmp_path), "--without-pip", "--activators", ""])
assert cachedir_tag_file.read_text(encoding="utf-8") == "magic"


def test_create_vcs_ignore_exists(tmp_path):
git_ignore = tmp_path / ".gitignore"
git_ignore.write_text("magic", encoding="utf-8")
Expand Down

0 comments on commit 2a29a1b

Please sign in to comment.