<commit_before>"""
Classes to copy files between build and web servers.

"Syncers" copy files from the local machine, while "Pullers" copy files to the
local machine.
"""

import getpass
import logging
import os
import shutil

from django.conf import settings
from django.core.exceptions import SuspiciousFileOperation
from django.core.files.storage import get_storage_class

from readthedocs.core.utils import safe_makedirs
from readthedocs.core.utils.extend import SettingsOverrideObject


log = logging.getLogger(__name__)
storage = get_storage_class()()


class BaseSyncer:

    """A base object for syncers and pullers."""

    @classmethod
    def copy(cls, path, target, is_file=False, **kwargs):
        raise NotImplementedError


class LocalSyncer(BaseSyncer):

    @classmethod
    def copy(cls, path, target, is_file=False, **kwargs):
        """A copy command that works with files or directories."""
        log.info('Local Copy %s to %s', path, target)
        if is_file:
            if path == target:
                # Don't copy the same file over itself
                return
            if os.path.exists(target):
                os.remove(target)

            # Create containing directory if it doesn't exist
            directory = os.path.dirname(target)
            safe_makedirs(directory)

            shutil.copy2(path, target)<commit_msg>Add a null syncer that doesn't sync files<commit_after>"""
Classes to copy files between build and web servers.

"Syncers" copy files from the local machine, while "Pullers" copy files to the
local machine.
"""

import getpass
import logging
import os
import shutil

from django.conf import settings
from django.core.files.storage import get_storage_class

from readthedocs.core.utils import safe_makedirs
from readthedocs.core.utils.extend import SettingsOverrideObject


log = logging.getLogger(__name__)
storage = get_storage_class()()


class BaseSyncer:

    """A base object for syncers and pullers."""

    @classmethod
    def copy(cls, path, target, is_file=False, **kwargs):
        raise NotImplementedError


class NullSyncer:

    """A syncer that doesn't actually do anything"""

    @classmethod
    def copy(cls, path, target, is_file=False, **kwargs):
        pass  # noqa


class LocalSyncer(BaseSyncer):

    @classmethod
    def copy(cls, path, target, is_file=False, **kwargs):
        """A copy command that works with files or directories."""
        log.info('Local Copy %s to %s', path, target)
        if is_file:
            if path == target:
                # Don't copy the same file over itself
                return
            if os.path.exists(target):
                os.remove(target)

            # Create containing directory if it doesn't exist
            directory = os.path.dirname(target)
            safe_makedirs(directory)

            shutil.copy2(path, target)
{'fraction_non_alphanumeric': 0.08443363446838081, 'fraction_numerical': 0.0006949270326615705, 'mean_word_length': 2.922343324250681, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6248752', 'n_tokens_mistral': 817, 'n_tokens_neox': 776, 'n_words': 276}