# Copyright (C) 2008 The Android Open Source Project
#
# 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.


class ManifestParseError(Exception):
    """Failed to parse the manifest file."""


class ManifestInvalidRevisionError(ManifestParseError):
    """The revision value in a project is incorrect."""


class ManifestInvalidPathError(ManifestParseError):
    """A path used in <copyfile> or <linkfile> is incorrect."""


class NoManifestException(Exception):
    """The required manifest does not exist."""

    def __init__(self, path, reason):
        super().__init__(path, reason)
        self.path = path
        self.reason = reason

    def __str__(self):
        return self.reason


class EditorError(Exception):
    """Unspecified error from the user's text editor."""

    def __init__(self, reason):
        super().__init__(reason)
        self.reason = reason

    def __str__(self):
        return self.reason


class GitError(Exception):
    """Unspecified internal error from git."""

    def __init__(self, command):
        super().__init__(command)
        self.command = command

    def __str__(self):
        return self.command


class UploadError(Exception):
    """A bundle upload to Gerrit did not succeed."""

    def __init__(self, reason):
        super().__init__(reason)
        self.reason = reason

    def __str__(self):
        return self.reason


class DownloadError(Exception):
    """Cannot download a repository."""

    def __init__(self, reason):
        super().__init__(reason)
        self.reason = reason

    def __str__(self):
        return self.reason


class NoSuchProjectError(Exception):
    """A specified project does not exist in the work tree."""

    def __init__(self, name=None):
        super().__init__(name)
        self.name = name

    def __str__(self):
        if self.name is None:
            return "in current directory"
        return self.name


class InvalidProjectGroupsError(Exception):
    """A specified project is not suitable for the specified groups"""

    def __init__(self, name=None):
        super().__init__(name)
        self.name = name

    def __str__(self):
        if self.name is None:
            return "in current directory"
        return self.name


class RepoChangedException(Exception):
    """Thrown if 'repo sync' results in repo updating its internal
    repo or manifest repositories.  In this special case we must
    use exec to re-execute repo with the new code and manifest.
    """

    def __init__(self, extra_args=None):
        super().__init__(extra_args)
        self.extra_args = extra_args or []


class HookError(Exception):
    """Thrown if a 'repo-hook' could not be run.

    The common case is that the file wasn't present when we tried to run it.
    """
