<commit_before>import os
import shutil
import sys
import stat
import errno
import logging
import subprocess
import pkg_resources
import cPickle as pickle
from itertools import islice
from datetime import datetime
from cStringIO import StringIO

import git
import pylons
import pymongo.bson
from webob import exc

from ming.orm.mapped_class import MappedClass
from ming.orm.property import FieldProperty
from ming.utils import LazyProperty

from pyforge import model as M
from pyforge.lib import helpers as h

log = logging.getLogger(__name__)

def on_import():
    GitRepository.CommitClass = GitCommit
    GitCommit.TreeClass = GitTree
    GitTree.BlobClass = GitBlob

class GitRepository(M.Repository):
    class __mongometa__:
        name='git-repository'

    def index(self):
        result = super(GitRepository, self).index()
        result.update(
            type_s='GitRepository')
        return result

    def _setup_paths(self, create_repo_dir=True):
        if not self.fs_path.endswith('/'): self.fs_path += '/'
        fullname = os.path.join(self.fs_path, self.name)
        try:
            os.makedirs(fullname if create_repo_dir else self.fs_path)
        except OSError, e: # pragma no cover
            if e.errno != errno.EEXIST: raise
        return fullname

    def _setup_special_files(self):
        magic_file = os.path.join(self.fs_path, self.name, '.SOURCEFORGE-REPOSITORY')
        with open(magic_file, 'w') as f:
            f.write('git')
        os.chmod(magic_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
        self._setup_receive_hook(
            pylons.c.app.config.script_name())

    def commit(self, hash):
        return self.CommitClass.from_repo_object(self._impl.commit(hash), self)

    def init(self):
        fullname = self._setup_paths()
        log.info('git init %s', fullname)
        result = subprocess.call(['git', 'init', '--quiet', '--bare', '--shared=all'],
                                 cwd=fullname)
        self._setup_special_files()
        self.status = 'ready'

    def init_as_clone(self, source_path):
        """Make this new repo be a clone of the one at source_path.

        Note that this is the opposite "direction" of git.Repo.clone().
        """
        fullname = self._setup_paths(create_repo_dir=False)
        log.info('git clone %s %s' % (source_path, fullname))
        # We may eventually require --template=...
        result = subprocess.call(['git', 'clone', '--bare', source_path, self.name],
                                 cwd=self.fs_path)
        # we don't want merge requests from the originating repo,
        # but local clones by default copy everything under the refs directory
        # so delete refs/requests (our custom place for storing refs) by hand
        requests = os.path.join(fullname, 'refs', 'requests')
        shutil.rmtree(requests, ignore_errors=True)
        self._setup_special_files()
        self.status = 'ready'

    def _log(self, **kwargs):
        kwargs.setdefault('topo_order', True)
        commits = self._impl.iter_commits(**kwargs)
        return [ self.CommitClass.from_repo_object(entry, self)
                 for entry in commits ]

    def log(self, branch='master', offset=0, limit=10):
        return self._log(rev=branch, skip=offset, max_count=limit)

    @LazyProperty
    def _impl(self):
        return git.Repo(self.full_fs_path)

    def __getattr__(self, name):
        return getattr(self._impl, name)

    def repo_tags(self):
        '''Override Artifact.tags'''
        return self._impl.tags

    def _setup_receive_hook(self, plugin_id):
        'Set up the git post-commit hook'
        tpl_fn = pkg_resources.resource_filename(
            'forgegit', 'data/post-receive_tmpl')
        config = pylons.config.get('__file__')
        text = h.render_genshi_plaintext(tpl_fn,
            executable=sys.executable,
            repository=plugin_id,
            config=config)
        fn = os.path.join(self.fs_path, self.name, 'hooks', 'post-receive')
        with open(fn, 'w') as fp:
            fp.write(text)
        os.chmod(fn, 0755)

class GitCommit(M.Commit):<commit_msg>[#568] - Force early failure on infinite recursion problems<commit_after>import os
import shutil
import sys
import stat
import errno
import logging
import subprocess
import pkg_resources
import cPickle as pickle
from itertools import islice
from datetime import datetime
from cStringIO import StringIO

import git
import pylons
import pymongo.bson
from webob import exc

from ming.orm.mapped_class import MappedClass
from ming.orm.property import FieldProperty
from ming.utils import LazyProperty

from pyforge import model as M
from pyforge.lib import helpers as h

log = logging.getLogger(__name__)

def on_import():
    GitRepository.CommitClass = GitCommit
    GitCommit.TreeClass = GitTree
    GitTree.BlobClass = GitBlob

class GitRepository(M.Repository):
    class __mongometa__:
        name='git-repository'

    def index(self):
        result = super(GitRepository, self).index()
        result.update(
            type_s='GitRepository')
        return result

    def _setup_paths(self, create_repo_dir=True):
        if not self.fs_path.endswith('/'): self.fs_path += '/'
        fullname = os.path.join(self.fs_path, self.name)
        try:
            os.makedirs(fullname if create_repo_dir else self.fs_path)
        except OSError, e: # pragma no cover
            if e.errno != errno.EEXIST: raise
        return fullname

    def _setup_special_files(self):
        magic_file = os.path.join(self.fs_path, self.name, '.SOURCEFORGE-REPOSITORY')
        with open(magic_file, 'w') as f:
            f.write('git')
        os.chmod(magic_file, stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH)
        self._setup_receive_hook(
            pylons.c.app.config.script_name())

    def commit(self, hash):
        return self.CommitClass.from_repo_object(self._impl.commit(hash), self)

    def init(self):
        fullname = self._setup_paths()
        log.info('git init %s', fullname)
        result = subprocess.call(['git', 'init', '--quiet', '--bare', '--shared=all'],
                                 cwd=fullname)
        self._setup_special_files()
        self.status = 'ready'

    def init_as_clone(self, source_path):
        """Make this new repo be a clone of the one at source_path.

        Note that this is the opposite "direction" of git.Repo.clone().
        """
        fullname = self._setup_paths(create_repo_dir=False)
        log.info('git clone %s %s' % (source_path, fullname))
        # We may eventually require --template=...
        result = subprocess.call(['git', 'clone', '--bare', source_path, self.name],
                                 cwd=self.fs_path)
        # we don't want merge requests from the originating repo,
        # but local clones by default copy everything under the refs directory
        # so delete refs/requests (our custom place for storing refs) by hand
        requests = os.path.join(fullname, 'refs', 'requests')
        shutil.rmtree(requests, ignore_errors=True)
        self._setup_special_files()
        self.status = 'ready'

    def _log(self, **kwargs):
        kwargs.setdefault('topo_order', True)
        commits = self._impl.iter_commits(**kwargs)
        return [ self.CommitClass.from_repo_object(entry, self)
                 for entry in commits ]

    def log(self, branch='master', offset=0, limit=10):
        return self._log(rev=branch, skip=offset, max_count=limit)

    @LazyProperty
    def _impl(self):
        return git.Repo(self.full_fs_path)

    def __getattr__(self, name):
        assert type(self) != type(self._impl), 'Problem looking up %s' % name
        return getattr(self._impl, name)

    def repo_tags(self):
        '''Override Artifact.tags'''
        return self._impl.tags

    def _setup_receive_hook(self, plugin_id):
        'Set up the git post-commit hook'
        tpl_fn = pkg_resources.resource_filename(
            'forgegit', 'data/post-receive_tmpl')
        config = pylons.config.get('__file__')
        text = h.render_genshi_plaintext(tpl_fn,
            executable=sys.executable,
            repository=plugin_id,
            config=config)
        fn = os.path.join(self.fs_path, self.name, 'hooks', 'post-receive')
        with open(fn, 'w') as fp:
            fp.write(text)
        os.chmod(fn, 0755)

class GitCommit(M.Commit):
{'fraction_non_alphanumeric': 0.10442435775451951, 'fraction_numerical': 0.002021883920076118, 'mean_word_length': 2.670449585333915, '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': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3204562', 'n_tokens_mistral': 2625, 'n_tokens_neox': 2539, 'n_words': 648}