#
# Copyright (c) SAS Institute Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#


from testrunner import testhelp
from testutils import sock_utils
import copy
import itertools
import os
import shutil
import tempfile
import time
import SimpleHTTPServer

from conary_test import recipes
from conary_test import rephelp

#conary
from conary import callbacks
from conary import conarycfg, conaryclient
from conary import errors as gerrors
from conary import sqlite3
from conary import trove
from conary import versions
from conary.cmds import updatecmd
from conary.deps import arch, deps
from conary.lib import httputils
from conary.lib import util
from conary.repository import changeset, calllog, errors, filecontainer
from conary.repository import netclient
from conary.server import server as conaryserver


class NetclientTest(rephelp.RepositoryHelper):
    def testGetFileContents(self):
        # create a testcase:source component
        # add a file called "foo"
        # rename file to "bar"
        # verify that "bar"'s contents can be retrieved
        origDir = os.getcwd()
        self.resetRepository()
        self.resetWork()
        os.chdir(self.workDir)
        self.newpkg('testcase')
        os.chdir('testcase')
        self.writeF
ile('testcase.recipe', recipes.testRecipe1)
        self.writeFile('foo', 'hi\n')
        self.addfile('testcase.recipe')
        self.addfile('foo', binary = True)
        self.commit()
        self.rename('foo', 'bar')
        self.commit()
        repos = self.openRepository()
        # find the version of the testcase:source component
        troveVer = repos
.getAllTroveLeaves('localhost',
                  { 'testcase:source' : None })['testcase:source'].keys()[0]
        # find the version of the file
        barId = None
        for f in repos.iterFilesInTrove('testcase:source', troveVer,
                                        deps.Flavor(), withFiles=True):
            pathId, path, fileId, version, fileObj = f
            if path == 'bar':
                barId = (fileId, version)
            elif path == 'testcase.recipe':
                recipeIds = (fileId, version)
        if barId is None:
            self.fail('version of renamed file not found')
        f = repos.getFileContents( [ barId ])[0]
        assert(f.get().read() == 'hi\n')

        # get multiple contents at the same time
        f, recipe = repos.getFileContents([ barId, recipeIds ])
        assert(f.get().read() == 'hi\n')
        assert(recipe.get().read() == recipes.testRecipe1)
        os.chdir(origDir)

    def testFileContentsErrors(self):
        # set up two repositores. create a shadow of test:runtime from
        # the localhost repository into the localhost1 repository.
        # Ask the localhost1 for the file contents from a file that
        # resides on localhost.  The file stream does not exist on
        # localhost1, so it should cause an exception.
        self.openRepository(1)
        t = self.addQuickTestComponent('test:runtime', '1.0-1-1')
        self.addCollection('test', '1.0-1-1', [':runtime'])
        # get the fileId and version of the file that we created.
        fileList = list(t.iterFileList())
        assert(len(fileList) == 1)
        fileId, version = fileList[0][2:4]
        # create the shadow in localhost1
        self.mkbranch("1.0-1-1", "localhost1@rpl:shadow", "test",
                      shadow = True, binaryOnly=True)
        # build up the version string that points at the shadow
        shadowVersion = versions.VersionFromString(
            '/localhost@rpl:linux//localhost1@rpl:shadow/1.0-1-1')
        # open the repository here when the proxy we use will be up to date
        repos = self.openRepository()
        try:
            repos.getFileContents([(fileId, shadowVersion)])
        except errors.FileStreamNotFound, e:
            assert((e.fileId, e.fileVer) == (fileId, shadowVersion))
        else:
            assert(0)

        # ask for a random fileId, should always fail
        bogusV = versions.VersionFromString('/localhost@rpl:linux/1.0-1-1')
        bogusFileId = '1' * 20
        bogusPathId = '2' * 16
        try:
            repos.getFileContents([(bogusFileId, bogusV)])
        except errors.FileStreamNotFound, e:
            assert((e.fileId, e.fileVer) == (bogusFileId, bogusV))
        else:
            assert(0)

        try:
            repos.getFileVersions([(bogusPathId, bogusFileId, bogusV)])
        except errors.FileStreamMissing, e:
            assert(e.fileId == bogusFileId)
        else:
            assert(0)

        # try getting the contents of a file which doesn't have contents
        t = self.addComponent('symtest:runtime', '1.0-1-1',
                              fileContents = [ ('/symlink',
                                                rephelp.Symlink('something')) ])
        fileList = list(t.iterFileList())
        assert(len(fileList) == 1)
        linkFileId, linkVersion = fileList[0][2:4]
        try:
            repos.getFileContents([ (linkFileId, linkVersion) ])
        except errors.FileHasNoContents, e:
            assert((e.fileId, e.fileVer) == (linkFileId, linkVersion))
        else:
            assert(0)

        # play a nasty trick on the server by removing the contents
        # to test missing contents error handling.  It's OK to do this
        # since the server is about to be reset anyway...
        server = self.servers.getServer(0)
        shutil.rmtree(server.contents.getPath())
        try:
            f = repos.getFileContents([ (fileId, version) ])
        except errors.FileContentsNotFound, e:
            assert((e.fileId, e.fileVer) == (fileId, version))
        else:
            assert(0)

    def testAnonymousAccess(self):
        (built, d) = self.buildRecipe(recipes.testRecipe1, "TestRecipe1")
        repos = self.openRepository()
        items = repos.getTroveLeavesByLabel(
                            { 'testcase' : { self.cfg.buildLabel : None } } )
        assert(len(items) == 1)

        port = self.cfg.repositoryMap['localhost'].split(':')[-1].split('/')[0]
        cfg = copy.copy(self.cfg)
        cfg.user = self.cfg.user.__class__()
        client = conaryclient.ConaryClient(cfg).getRepos()

        items = client.getTroveLeavesByLabel(
                            { 'testcase' : { self.cfg.buildLabel : None } } )
        assert(len(items) == 1)

    def _testBranchPathIds(self, shadow):
        repos = self.openRepository()
        self.makeSourceTrove("PathIdTest", recipes.pathIdTest1)
        self.logFilter.add()
        version = self.cookFromRepository("PathIdTest")[0][1]
        self.logFilter.remove()
        version = versions.VersionFromString(version)
        trunk = version.branch()

        if shadow:
            branch = version.createShadow(
                                    versions.Label("localhost@rpl:branch"))
        else:
            branch = version.createBranch(
                                    versions.Label("localhost@rpl:branch"))

        ids = repos.getPackageBranchPathIds("PathIdTest:source", trunk)
        assert(len(ids) == 3)

        self.mkbranch("1.0-1", "@rpl:branch", "PathIdTest:source",
                      shadow = shadow)

        self.updateSourceTrove("PathIdTest", recipes.pathIdTest2,
                               "localhost@rpl:branch")
        version = self.cookFromRepository("PathIdTest",
                    buildLabel = versions.Label("localhost@rpl:branch"))[0][1]
        branch = versions.VersionFromString(version).branch()
        branchIds = repos.getPackageBranchPathIds("PathIdTest:source", branch)

        ids = repos.getPackageBranchPathId