#
# 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 decorators

import os
import stat
import shutil
import tempfile
from testrunner import testhelp
import SimpleHTTPServer

from conary import files, versions, rpmhelper
from conary import trove as trovemod
VFS = versions.VersionFromString
from conary.lib import log
from conary.lib import openpgpfile, util
from conary_test import rephelp
from conary.build import errors
from conary.build import lookaside
from conary.build import source
from conary_test import resources
from conary_test.cvctest.buildtest import policytest


class SourceTest(rephelp.RepositoryHelper):

    def testSourceManifest(self):
        recipestr = """
class TestSourceManifest(PackageRecipe):
    name = 'test'
    version = '1'
    clearBuildReqs()
    
    def setup(r):
        # random files we have around in archive...
        r.addArchive('asdf.tar.gz', dir='/', package='asdf')
        r.addSource('sourcefile', dir='/var/test/')
"""
        (built, d) = self.buildRecipe(recipestr, "TestSourceManifest")
        repos = self.openRepository()
        for troveName, troveVersionString, troveFlavor in built:
            for pathId, path, fileId, version, fileObj in repos.iterFilesInTrove(
                    troveName, versions.VersionFromString(troveVersionString), troveFlavor,
                withFiles=True):
                if 'fdsa' in path or 'bam' in path:
                    assert(troveName == 'asdf:runtime')
                elif 'sourcefile' in path:
                    assert(troveName == 'test:runtime')



    def testISOArchiveJoliet(self):
        recipestr = """
class TestISOArchive(PackageRecipe):
    name = 'test'
    version = '1'
    clearBuildReqs()
    
    def setup(r):
        r.addArchive('jcd.iso', dir='/')
        r.SetModes('%(bindir)s/touch', 0755)
"""
        trove = self.build(recipestr, "TestISOArchive")
        repos = self.openRepository()
        paths = []
        for pathId, path, fileId, version, fileObj in repos.iterFilesInTrove(
                trove.getName(), trove.getVersion(), trove.getFlavor(),
                withFiles=True):
            paths.append(path)
        assert sorted(paths) == [
            '/a/b', '/aaa/blah', '/b/bar', '/usr/bin/touch']

    def testISOArchiveRockRidge(self):
        recipestr = """
class TestISOArchive(PackageRecipe):
    name = 'test'
    version = '1'
    clearBuildReqs()
    
    def setup(r):
        r.addArchive('rrcd.iso', dir='/')
        r.SetModes('%(bindir)s/touch', 0755)
"""
        trove = self.build(recipestr, "TestISOArchive")
        repos = self.openRepository()
        paths = []
        for pathId, path, fileId, version, fileObj in repos.iterFilesInTrove(
                trove.getName(), trove.getVersion(), trove.getFlavor(),
                withFiles=True):
            paths.append(path)
        assert sorted(paths) == [
            '/a/b', '/aaa/blah', 
'/b/bar', '/usr/bin/touch']

    @decorators.requireBinary("xz")
    def testSourceTest1(self):
        """
        Test build.source
        """

        recipestr = """
class TestSource(PackageRecipe):
    name = 'tmpwatch'
    version = '2.9
.0'
    clearBuildReqs()
    
    def setup(r):
        # test unpacking and extracting from an RPM
        r.addArchive('tmpwatch-2.9.0.tar.gz', rpm='tmpwatch-2.9.0-2.src.rpm')

        # test unpacking and extracting from a src bz2 RPM
        r.addSource('mkinitrd.spec', rpm='rpm-with-bzip-5.0.29-1.src.rpm')

        # test unpacking and extracting from a bz2 RPM
        r.addArchive('rpm-with-bzip-5.0.29-1.i386.rpm')

        # test unpacking and extracting from an lzma RPM
        r.addArchive('gnome-main-menu-0.9.10-26.x86_64.rpm')

        # test unpacking from a tar.xz (CNY-3207)
        r.addArchive('foo.tar.xz', dir='/')

        # test applying a patch
        r.addPatch('tmpwatch.fakebug.patch')
        # test taking that patch right back out with a string to extraArgs
        r.addPatch('tmpwatch.fakebug.patch', extraArgs='--reverse')
        # test putting the patch back in again with a list to extraArgs this time
        r.addPatch('tmpwatch.fakebug.patch', extraArgs=['--ignore-whitespace',])
        # test the dest= capability of addSource
        r.addSource('tmpwatch.fakebug.patch', dest='foo')
        r.addSource('tmpwatch.fakebug.patch', dir='/asdf', dest='foo')
        r.addSource('tmpwatch.fakebug.patch', dest='/asdf/foo2%%')
        r.addSource('tmpwatch.fakebug.patch', dest='/asdf/')
        # make sure spaces are OK
        r.addSource('name with spaces')
        r.addSource('localfoo')
        r.addSource('local name with spaces')
        r.addAction('ls foo')
        r.addAction('ls foo', dir='/asdf')
        r.addAction('ls foo2%%', dir='/asdf')
        r.addAction('ls tmpwatch.fakebug.patch', dir='/asdf')
        r.addArchive('tmpwatch-2.9.0.tar.gz', rpm='tmpwatch-2.9.0-2.src.rpm',
                        dir='/asdf')
        r.addAction('ls tmpwatch-2.9.0', dir='/asdf')
        # XXX I'm not sure what this was intended to show
        #r.addAction('ls tmpwatch-2.9.0', dir='%(destdir)s/asdf')
        r.addPatch('tmpwatch.fakebug.patch', dir='/asdf/tmpwatch-2.9.0')
"""
        self.resetWork()
        self.resetRepository()
        self.repos = self.openRepository()
        origDir = os.getcwd()
        os.chdir(self.workDir)
        self.newpkg('tmpwatch')
        os.chdir('tmpwatch')
        file('localfoo', 'w').close()
        file('local name with spaces', 'w').close()
        self.writeFile('tmpwatch.recipe', recipestr)
        self.addfile('tmpwatch.recipe')
        self.addfile('localfoo', text=True)
        self.addfile('local name with spaces', text=True)
        self.commit()
        os.chdir('..')
        shutil.rmtree('tmpwatch')
        os.chdir(origDir)
        self.resetCache()

        # ensure that we are testing the /usr/bin/xz path here
        realExists = os.path.exists
        def access_xz(*args):
            if args[0].endswith('/unlzma'):
                return False
            return realExists(*args)
        self.mock(os.path, 'exists', access_xz)

        self.cookItem(self.repos, self.cfg, 'tmpwatch', requireCleanSources=False)

    @decorators.requireBinary("unlzma")
    def testSourceTestUnlzma(self):
        """
        Test build.source
        """

        recipestr = """
class TestSource(PackageRecipe):
    name = 'gnome-main-menu'
    version = '0.9.10'
    clearBuildReqs()
    
    def setup(r):
        # test unpacking and extracting from an lzma RPM if xz not available
        r.addArchive('gnome-main-menu-0.9.10-26.x86_64.rpm', dir='/')
        del r.NonMultilibDirectories
"""
        # ensure that we are testing the older /usr/bin/unlzma path here
        # to make sure this still works on SLES10
        realExists = os.path.exists
        def access_lzma(*args):
            if args[0].endswith('/xz'):
                return False
            return realExists(*args)
        self.mock(os.path, 'exists', access_lzma)
        (built, d) = self.buildRecipe(recipestr, "TestSource")
        assert 'gnome-main-menu:runtime' in [x[0] for x in built]

    def testSourceTestMissinglzma(self):
        """
        Test build.source
        """

        recipestr = """
class TestSource(PackageRecipe):
    name = 'gnome-main-menu'
    version = '0.9.10'
    clearBuildReqs()
    
    def setup(r):
        # test unpacking and extracting from an lzma RPM if xz not available
        r.addArchive('gnome-main-menu-0.9.10-26.x86_64.rpm', dir='/')
"""
        # make sure sane error exists if neither xz nor unlzma provided
       