# Copyright (C) 2012-2015 Codethink Limited
#
# 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 of the License.
#
# 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
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.


import unittest
import urllib2
import os

import cliapp
import fs.memoryfs

import morphlib
import morphlib.gitdir_tests


class FakeApplication(object):

    def __init__(self):
        self.settings = {
            'verbose': True
        }

    def status(self, msg):
        pass


class LocalRepoCacheTests(unittest.TestCase):

    def setUp(self):
        aliases = ['upstream=git://example.com/#example.com:%s.git']
        repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(aliases)
        tarball_base_url = 'http://lorry.example.com/tarballs/'
        self.reponame = 'upstream:reponame'
        self.repourl = 'git://example.com/reponame'
        escaped_url = 'git___example_com_reponame'
        self.tarball_url = '%s%s.tar' % (tarball_base_url, escaped_url)
        self.cachedir = '/cache/dir'
        self.cache_path = '%s/%s' % (self.cachedir, escaped_url)
        self.remotes = {}
        self.fetched = []
        self.removed = []
        self.lrc = morphlib.localrepocache.LocalRepoCache(
            FakeApplication(), self.cachedir, repo_resolver, tarball_base_url)
        self.lrc.fs = fs.memoryfs.MemoryFS()
        self.lrc._git = self.fake_git
        self.lrc._fetch = self.not_found
        self.lrc._mkdtemp = self.fake_mkdtemp
        self.lrc._new_cached_repo_instance = self.new_cached_repo_instance
        self._mkdtemp_count = 0

    def fake_git(self, args, **kwargs):
        if args[0] == 'clone':
            

        elif args[0:2] == ['remote', 'set-url']:
            remote = args[2]
            url = args[3]
            self.remotes[remote] = {'url': url}
        elif args[0:2] == ['config', 'remote.origin.url']:
            remote = 'origin'
            url = args[2]
            self.remotes[remote] = {'url': url}
        elif args[0:2] == ['config', 'remote.origin.mirror']:
            remote = 'origin'
        elif args[0:2] == ['config', 'remote.origin.fetch']:
            remote = 'origin'
        else:
            raise NotImplementedError()

    def fake_mkdtemp(self, dirname):
        thing = "foo"+str(self._mkdtemp_count)
        self._mkdtemp_count += 1
        self.lrc.fs.makedir(dirname+"/"+thing)
        return thing

    def new_cached_repo_instance(self, *args):
        with morphlib.gitdir_tests.allow_nonexistant_git_repos():
            return morphlib.cachedrepo.CachedRepo(
                FakeApplication(), *args)

    def not_found(self, url, path):
        raise cliapp.AppException('Not found')

    def test_has_not_got_shortened_repo_initially(self):
        self.assertFalse(self.lrc.has_repo(self.reponame))

    def test_has_not_got_absolute_repo_initially(self):
        self.assertFalse(self.lrc.has_repo(self.repourl))

    def test_caches_shortened_repository_on_request(self):
        self.lrc.cache_repo(self.reponame)
        self.assertTrue(self.lrc.has_repo(self.reponame))
        self.assertTrue(self.lrc.has_repo(self.repourl))

    def test_caches_absolute_repository_on_request(self):
        self.lrc.cache_repo(self.repourl)
        self.assertTrue(self.lrc.has_repo(self.reponame))
        self.assertTrue(self.lrc.has_repo(self.repourl))

    def test_cachedir_does_not_exist_initially(self):
        self.assertFalse(self.lrc.fs.exists(self.cachedir))

    def test_creates_cachedir_if_missing(self):
        self.lrc.cache_repo(self.repourl)
        self.assertTrue(self.lrc.fs.exists(self.cachedir))

    def test_happily_caches_same_repo_twice(self):
        self.lrc.cache_repo(self.repourl)
        self.lrc.cache_repo(self.repourl)

    def test_fails_to_cache_when_remote_does_not_exist(self):
        def fail(args, **kwargs):
            self.lrc.fs.makedir(args[4])
            raise cliapp.AppException('')
        self.lrc._git = fail
        self.assertRaises(morphlib.localrepocache.NoRemote,
                          self.lrc.cache_repo, self.repourl)

    def test_does_not_mind_a_missing_tarball(self):
        self.lrc.cache_repo(self.repourl)
        self.assertEqual(self.fetched, [])

    def test_fetches_tarball_when_it_exists(self):
        self.lrc._fetch = lambda url, path: self.fetched.append(url)
        self.unpacked_tar = ""
        self.mkdir_path = ""

        with morphlib.gitdir_tests.monkeypatch(
                morphlib.cachedrepo.CachedRepo, 'update', lambda self: None):
            self.lrc.cache_repo(self.repourl)

        self.assertEqual(self.fetched, [self.tarball_url])
        self.assertFalse(self.lrc.fs.exists(self.cache_path + '.tar'))
        self.assertEqual(self.remotes['origin']['url'], self.repourl)

    def test_gets_cached_shortened_repo(self):
        self.lrc.cache_repo(self.reponame)
        cached = self.lrc.get_repo(self.reponame)
        self.assertTrue(cached is not None)

    def test_gets_cached_absolute_repo(self):
        self.lrc.cache_repo(self.repourl)
        cached = self.lrc.get_repo(self.repourl)
        self.assertTrue(cached is not None)

    def test_get_repo_raises_exception_if_repo_is_not_cached(self):
        self.assertRaises(Exception, self.lrc.get_repo, self.repourl)

    def test_escapes_repourl_as_filename(self):
        escaped = self.lrc._escape(self.repourl)
        self.assertFalse('/' in escaped)

    def test_noremote_error_message_contains_repo_name(self):
        e = morphlib.localrepocache.NoRemote(self.repourl, [])
        self.assertTrue(self.repourl in str(e))

    def test_avoids_caching_local_repo(self):
        self.lrc.fs.makedir('/local/repo', recursive=True)
        self.lrc.cache_repo('file:///local/repo')
        cached = self.lrc.get_repo('file:///local/repo')
        assert cached.path == '/local/repo'

self.assertEqual(len(args), 5)
            remote = args[3]
            local = args[4]
            self.remotes['origin'] = {'url': remote, 'updates': 0}
            self.lrc.fs.makedir(local, recursive=True)