Exemplo n.º 1
0
class Tesserae(object):
    CONFIG_TEMPLATE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates/config")
    ROOT_DIRECTORY = ".tesserae"

    LS_HEADER = ("Id", "Title", "Status", "Type", "Priority", "Author", "Last updated")

    def __init__(self, path):
        self._git = Git(path)
        self._path = path
        self._configpath = os.path.join(self.tesseraepath, "config")

    @property
    def path(self):
        return self._path

    @property
    def tesseraepath(self):
        return os.path.join(os.path.dirname(self._git.git_dir), Tesserae.ROOT_DIRECTORY)

    @property
    def configpath(self):
        return self._configpath

    def _is_tesserae_repo(self):
        """
            Checks whether the path is a tesserae repository or not.
        """
        try:
            return os.path.exists(self.tesseraepath)
        except Gittle.NoGitRepository:
            return False

    def _get_real_tessera_id(self, tessera_id):
        """
            Returns the real tessera id.
            This method evaluates the full tessera id of a short tessera id.
        """
        try:
            return os.path.basename(glob(os.path.join(self.tesseraepath, tessera_id + "*"))[0])
        except IndexError:
            raise TesseraNotFoundError(tessera_id)

    def _get_all_tesserae(self):
        """
            Returns all tesserae.
        """
        tesserae = []
        for tessera_id in os.listdir(self.tesseraepath):
            path = os.path.join(self.tesseraepath, tessera_id)
            if not os.path.isdir(path):
                continue

            tesserae.append(Tessera(tessera_id, path))
        return tesserae

    def init(self):
        """
            Initialize empty git tesserae repository inside git repository.
        """
        try:
            self._git.is_working()
        except Gittle.NoGitRepository:
            print("error: not a git repository")
            return False

        if self._is_tesserae_repo():
            print("error: already initialized tesserae repository here")
            return False

        os.makedirs(self.tesseraepath)
        copyfile(Tesserae.CONFIG_TEMPLATE, self._configpath)

        self._git.commit_repo(self, "tesserae initialized")
        print("Initialized empty git tesserae repository in %s" % self.tesseraepath)
        return True

    @verify_tessera_path
    @check_tessera_id
    def show(self, tessera_id):
        """
            Shows a specific tessera by passing the tessera_id parameter.
        """
        t = Tessera(tessera_id, os.path.join(self.tesseraepath, tessera_id))
        print(t.raw_tessera_file_content)
        return True

    @verify_tessera_path
    def ls(self, order_by, order_type, filter_types):
        """
            Lists all tesserae and show basic information.
        """
        tesserae = self._get_all_tesserae()

        if not tesserae:
            print("no tesserae created yet. Use git tessera create 'title' to create a new tessera")
            return True

        rows = [(t.short_id, t.title, ", ".join(t.keywords.get("status", ["unknown"])), ", ".join(t.keywords.get("type", ["unknown"])), t.keywords.get("priority", ["0"])[0], t.metadata.get("author", ["unknown"]), t.metadata.get("updated"))
                for t in tesserae if not filter_types or filter_types.intersection(t.keywords.get("type"))]

        if not rows:
            print("no tesserae found which matched your query")
            return True

        if order_by:
            order_by = order_by.lower()
            headers = [x.lower() for x in Tesserae.LS_HEADER]
            try:
                index = headers.index(order_by)
            except ValueError:
                raise TesseraError("cannot order by '%s' because this columns does not exist. Available colums are: '%s'" % (order_by, headers))

            rows = sorted(rows, key=lambda r: float(r[index]) if r[index].isdigit() else r[index], reverse=order_type == "desc")

        rows.insert(0, Tesserae.LS_HEADER)
        widths = [max(map(len, column)) for column in zip(*rows)]
        for n, r in enumerate(rows):
            print("  ".join(data.ljust(width) for data, width in zip(r, widths)))
            if n == 0:
                print("=" * (sum(widths) + 2 * len(widths)))
        return True

    @verify_tessera_path
    def create(self, title):
        """
            Creates a new tessera.
        """
        tessera = Tessera.create(self.tesseraepath, title)

        if not Editor.open(tessera.tessera_file, TesseraConfig(self._configpath)):
            tessera.remove()
            return False

        if not self._git.add_tessera(tessera):
            print("error: cannot commit new tessera")
            tessera.remove()
            return False

        print("Created new tessera with id %s" % tessera.id)
        return True

    @verify_tessera_path
    @check_tessera_id
    def remove(self, tessera_id):
        """
            Removes a tessera by it's id.
        """
        tessera = Tessera(tessera_id, os.path.join(self.tesseraepath, tessera_id))
        tessera.remove()

        if not self._git.rm_tessera(tessera):
            print("error: cannot remove tessera")
            return False

        print("Removed tessera with id '%s'" % tessera.id)
        return True

    @verify_tessera_path
    @check_tessera_id
    def edit(self, tessera_id):
        """
            Edits a tessera by it's id.
        """
        tessera = Tessera(tessera_id, os.path.join(self.tesseraepath, tessera_id))

        if not Editor.open(tessera.tessera_file, TesseraConfig(self._configpath)):
            print("error: cannot updated tessera")
            return False

        tessera.update()

        if not self._git.update_tessera(tessera):
            print("error: cannot commit updated tessera")
            return False

        print("Updated tessera with id %s" % tessera.id)
        return True