#    test_do.py -- Blackbox tests for bd-do.
#    Copyright (C) 2007 James Westby <jw+debian@jameswestby.net>
#
#    This file is part of bzr-builddeb.
#
#    bzr-builddeb 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; either version 2 of the License, or
#    (at your option) any later version.
#
#    bzr-builddeb 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 bzr-builddeb; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

import os
import tarfile

from debian.changelog import (
    Changelog,
    Version,
)
from debian.deb822 import Deb822


from .....tests.blackbox import ExternalBase


TRIVIAL_PATCH = """--- /dev/null	2012-01-02 01:09:10.986490031 +0100
+++ base/afile	2012-01-02 20:03:59.710666215 +0100
@@ -0,0 +1 @@
+a
"""


class TestDo(ExternalBase):
    package_name = "test"
    package_version = Version("0.1")

    commited_file = "commited_file"
    uncommited_file = "uncommited_file"
    unadded_file = "unadded_file"

    def make_changelog(self, version=None):
        if version is None:
            version = self.package_version
        c = Changelog()
        c.new_block()
        c.version = Version(version)
        c.package = self.package_name
        c.distributions = "unstable"
        c.urgency = "low"
        c.author = "James Westby <jw+debian@jameswestby.net>"
        c.date = "Thu,  3 Aug 2006 19:16:22 +0100"
        c.add_change("")
        c.add_change("  *  test build")
        c.add_change("")
        return c

    def make_unpacked_source(self):
        """Create an unpacked source tree in a branch.

        Return the working tree
        """
        tree = self.make_branch_and_tree(".")
        cl_file = "debian/changelog"
        source_files = ["debian/"] + [cl_file]
        self.build_tree(source_files)
        c = self.make_changelog()
        with open(cl_file, "w") as f:
            c.write_to_open_file(f)
        tree.add(source_files)
        source = Deb822()
        source["Source"] = self.package_name
        binary = Deb822()
        binary["Package"] = self.package_name
        binary["Architecture"] = "all"
        with open("debian/control", "wb") as f:
            source.dump(f)
            f.write(b"\n")
            binary.dump(f)
        tree.add("debian/control")

        self.build_tree(["debian/test-file"])
        tree.add("debian/test-file")

        return tree

    def make_merge_mode_config(self, tree):
        os.mkdir(".bzr-builddeb/")
        with open(".bzr-builddeb/default.conf", "wb") as f:
            f.write(b"[BUILDDEB]\nmerge = True\n")
        tree.add([".bzr-builddeb/", ".bzr-builddeb/default.conf"])

    def make_upstream_tarball(self):
        self.build_tree(["test-0.1/", "test-0.1/a"])
        tar = tarfile.open(os.path.join("..", "test_0.1.orig.tar.gz"), "w:gz")
        try:
            tar.add("test-0.1")
        finally:
            tar.close()

    def build_dir(self):
        return os.path.join(
            "..", "build-area", self.package_name + "-" + str(self.package_version)
        )

    def assertInBuildDir(self, files):
        build_dir = self.build_dir()
        for filename in files:
            self.assertPathExists(os.path.join(build_dir, filename))

    def assertNotInBuildDir(self, files):
        build_dir = self.build_dir()
        for filename in files:
            self.assertPathDoesNotExist(os.path.join(build_dir, filename))

    def test_bd_do_registered(self):
        self.run_bzr("bd-do --help")

    def test_bd_do_not_merge(self):
        tree = self.make_unpacked_source()
        self.build_tree(["other", "more-other"])
        tree.add(["other", "more-other"])
        self.run_bzr_error(
            [
                "This command only works for merge mode packages.",
                "See /usr/share/doc/bzr-builddeb/user_manual"
                "/merge.html for more information.",
            ],
            "bd-do true",
        )

    def test_fails_no_changelog(self):
        tree = self.make_branch_and_tree(".")
        self.make_merge_mode_config(tree)
        self.run_bzr_error(["Could not find changelog"], "bd-do true")

    def test_no_copy_on_fail(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr_error(
            ["Not updating the working tree as the command failed."],
            ["bd-do", "touch debian/do && false"],
        )
        self.assertPathDoesNotExist("debian/do")

    def test_copy_on_success(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "touch debian/do"])
        self.assertPathExists("debian/do")

    def test_apply_patches(self):
        tree = self.make_unpacked_source()
        self.build_tree(["debian/patches/", "debian/source/"])
        self.build_tree_contents(
            [
                ("debian/patches/series", "patch1\n"),
                ("debian/source/format", "3.0 (quilt)\n"),
                ("debian/patches/patch1", TRIVIAL_PATCH),
            ]
        )
        tree.smart_add([tree.basedir])
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "cp afile debian/afile"])
        self.assertPathExists("debian/afile")

    def test_removed_files_are_removed_in_branch(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "rm debian/test-file"])
        # It might be nice if this was actually gone, but that would involve
        # either a comaparison, or removing all the files, but the latter is
        # dangerous. I guess it's a TODO to implement the comparison.
        self.assertPathExists("debian/test-file")

    def test_new_directories_created(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "mkdir debian/dir"])
        self.assertPathExists("debian/dir")

    def test_contents_taken_from_export(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "echo a > debian/test-file"])
        self.assertFileEqual("a\n", "debian/test-file")

    def test_export_purged(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        self.run_bzr(["bd-do", "echo a > debian/test-file"])
        self.assertPathDoesNotExist(self.build_dir())

    def test_uses_shell(self):
        tree = self.make_unpacked_source()
        self.make_merge_mode_config(tree)
        self.make_upstream_tarball()
        old_shell = os.environ.get("SHELL")
        os.environ["SHELL"] = "touch debian/shell"
        try:
            self.run_bzr("bd-do")
        finally:
            if old_shell is not None:
                os.environ["SHELL"] = old_shell
            else:
                del os.environ["SHELL"]
        self.assertPathExists("debian/shell")
