Beispiel #1
0
class CounterStat(db.Model, helpers.Serializer):
    """
    Generic store for simple statistics.
    """

    name = db.Column(db.String(127), primary_key=True)
    counter_type = db.Column(db.String(30))

    counter = db.Column(db.Integer, default=0, server_default="0")
Beispiel #2
0
class MockChroot(db.Model, helpers.Serializer):
    """
    Representation of mock chroot
    """

    id = db.Column(db.Integer, primary_key=True)
    # fedora/epel/..., mandatory
    os_release = db.Column(db.String(50), nullable=False)
    # 18/rawhide/..., optional (mock chroot doesn"t need to have this)
    os_version = db.Column(db.String(50), nullable=False)
    # x86_64/i686/..., mandatory
    arch = db.Column(db.String(50), nullable=False)
    is_active = db.Column(db.Boolean, default=True)

    @property
    def name(self):
        """
        Textual representation of name of this chroot
        """
        return "{}-{}-{}".format(self.os_release, self.os_version, self.arch)

    @property
    def name_release(self):
        """
        Textual representation of name of this or release
        """
        return "{}-{}".format(self.os_release, self.os_version)

    @property
    def name_release_human(self):
        """
        Textual representation of name of this or release
        """
        return "{} {}".format(self.os_release, self.os_version)

    @property
    def os(self):
        """
        Textual representation of the operating system name
        """
        return "{0} {1}".format(self.os_release, self.os_version)

    @property
    def serializable_attributes(self):
        attr_list = super(MockChroot, self).serializable_attributes
        attr_list.extend(["name", "os"])
        return attr_list
Beispiel #3
0
class Krb5Login(db.Model, helpers.Serializer):
    """
    Represents additional user information for kerberos authentication.
    """

    __tablename__ = "krb5_login"

    # FK to User table
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)

    # 'string' from 'copr.conf' from KRB5_LOGIN[string]
    config_name = db.Column(db.String(30), nullable=False, primary_key=True)

    # krb's primary, i.e. 'username' from '*****@*****.**'
    primary = db.Column(db.String(80), nullable=False, primary_key=True)

    user = db.relationship("User", backref=db.backref("krb5_logins"))
Beispiel #4
0
class Group(db.Model, helpers.Serializer):
    """
    Represents FAS groups and their aliases in Copr
    """
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(127))

    # TODO: add unique=True
    fas_name = db.Column(db.String(127))

    @property
    def at_name(self):
        return u"@{}".format(self.name)

    def __str__(self):
        return self.__unicode__()

    def __unicode__(self):
        return "{} (fas: {})".format(self.name, self.fas_name)
Beispiel #5
0
class Action(db.Model, helpers.Serializer):
    """
    Representation of a custom action that needs
    backends cooperation/admin attention/...
    """

    id = db.Column(db.Integer, primary_key=True)
    # delete, rename, ...; see helpers.ActionTypeEnum
    action_type = db.Column(db.Integer, nullable=False)
    # copr, ...; downcase name of class of modified object
    object_type = db.Column(db.String(20))
    # id of the modified object
    object_id = db.Column(db.Integer)
    # old and new values of the changed property
    old_value = db.Column(db.String(255))
    new_value = db.Column(db.String(255))
    # additional data
    data = db.Column(db.Text)
    # result of the action, see helpers.BackendResultEnum
    result = db.Column(db.Integer,
                       default=helpers.BackendResultEnum("waiting"))
    # optional message from the backend/whatever
    message = db.Column(db.Text)
    # time created as returned by int(time.time())
    created_on = db.Column(db.Integer)
    # time ended as returned by int(time.time())
    ended_on = db.Column(db.Integer)

    def __str__(self):
        return self.__unicode__()

    def __unicode__(self):
        if self.action_type == helpers.ActionTypeEnum("delete"):
            return "Deleting {0} {1}".format(self.object_type, self.old_value)
        elif self.action_type == helpers.ActionTypeEnum("rename"):
            return "Renaming {0} from {1} to {2}.".format(
                self.object_type, self.old_value, self.new_value)
        elif self.action_type == helpers.ActionTypeEnum("legal-flag"):
            return "Legal flag on copr {0}.".format(self.old_value)

        return "Action {0} on {1}, old value: {2}, new value: {3}.".format(
            self.action_type, self.object_type, self.old_value, self.new_value)
Beispiel #6
0
class CoprChroot(db.Model, helpers.Serializer):
    """
    Representation of Copr<->MockChroot relation
    """

    buildroot_pkgs = db.Column(db.Text)
    mock_chroot_id = db.Column(db.Integer,
                               db.ForeignKey("mock_chroot.id"),
                               primary_key=True)
    mock_chroot = db.relationship("MockChroot",
                                  backref=db.backref("copr_chroots"))
    copr_id = db.Column(db.Integer, db.ForeignKey("copr.id"), primary_key=True)
    copr = db.relationship("Copr",
                           backref=db.backref(
                               "copr_chroots",
                               single_parent=True,
                               cascade="all,delete,delete-orphan"))

    comps_zlib = db.Column(db.LargeBinary(), nullable=True)
    comps_name = db.Column(db.String(127), nullable=True)

    def update_comps(self, comps_xml):
        self.comps_zlib = zlib.compress(comps_xml.encode("utf-8"))

    @property
    def buildroot_pkgs_list(self):
        return self.buildroot_pkgs.split()

    @property
    def comps(self):
        if self.comps_zlib:
            return zlib.decompress(self.comps_zlib).decode("utf-8")

    @property
    def comps_len(self):
        if self.comps_zlib:
            return len(zlib.decompress(self.comps_zlib))
        else:
            return 0

    @property
    def name(self):
        return self.mock_chroot.name

    @property
    def is_active(self):
        return self.mock_chroot.is_active
Beispiel #7
0
class Package(db.Model, helpers.Serializer):
    """
    Represents a single package in a project.
    """
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    # Source of the build: type identifier
    source_type = db.Column(db.Integer,
                            default=helpers.BuildSourceEnum("unset"))
    # Source of the build: description in json, example: git link, srpm url, etc.
    source_json = db.Column(db.Text)
    # True if the package is built automatically via webhooks
    webhook_rebuild = db.Column(db.Boolean, default=False)
    # enable networking during a build process
    enable_net = db.Column(db.Boolean,
                           default=False,
                           server_default="0",
                           nullable=False)

    # relations
    copr_id = db.Column(db.Integer, db.ForeignKey("copr.id"))
    copr = db.relationship("Copr", backref=db.backref("packages"))

    @property
    def dist_git_repo(self):
        if self.copr.is_a_group_project:
            return "@{}/{}/{}".format(self.copr.group.name, self.copr.name,
                                      self.name)
        else:
            return "{}/{}/{}".format(self.copr.owner.name, self.copr.name,
                                     self.name)

    @property
    def source_json_dict(self):
        return json.loads(self.source_json)

    @property
    def source_type_text(self):
        return helpers.BuildSourceEnum(self.source_type)

    @property
    def dist_git_url(self):
        if app.config["DIST_GIT_URL"]:
            return "{}/{}.git".format(app.config["DIST_GIT_URL"],
                                      self.dist_git_repo)
        return None
Beispiel #8
0
class Copr(db.Model, helpers.Serializer):
    """
    Represents a single copr (private repo with builds, mock chroots, etc.).
    """

    id = db.Column(db.Integer, primary_key=True)
    # name of the copr, no fancy chars (checked by forms)
    name = db.Column(db.String(100), nullable=False)
    # string containing urls of additional repos (separated by space)
    # that this copr will pull dependencies from
    repos = db.Column(db.Text)
    # time of creation as returned by int(time.time())
    created_on = db.Column(db.Integer)
    # description and instructions given by copr owner
    description = db.Column(db.Text)
    instructions = db.Column(db.Text)
    deleted = db.Column(db.Boolean, default=False)
    playground = db.Column(db.Boolean, default=False)

    # should copr run `createrepo` each time when build packages are changed
    auto_createrepo = db.Column(db.Boolean, default=True)

    # relations
    owner_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    owner = db.relationship("User", backref=db.backref("coprs"))
    mock_chroots = association_proxy("copr_chroots", "mock_chroot")

    # enable networking for the builds by default
    build_enable_net = db.Column(db.Boolean,
                                 default=True,
                                 server_default="1",
                                 nullable=False)

    __mapper_args__ = {"order_by": created_on.desc()}

    @property
    def repos_list(self):
        """
        Return repos of this copr as a list of strings
        """
        return self.repos.split()

    @property
    def active_chroots(self):
        """
        Return list of active mock_chroots of this copr
        """

        return filter(lambda x: x.is_active, self.mock_chroots)

    @property
    def build_count(self):
        """
        Return number of builds in this copr
        """

        return len(self.builds)

    @property
    def disable_createrepo(self):

        return not self.auto_createrepo

    @disable_createrepo.setter
    def disable_createrepo(self, value):

        self.auto_createrepo = not bool(value)

    def check_copr_chroot(self, chroot):
        """
        Return object of chroot, if is related to our copr or None
        """

        result = None
        # there will be max ~10 chroots per build, iteration will be probably
        # faster than sql query
        for copr_chroot in self.copr_chroots:
            if copr_chroot.mock_chroot_id == chroot.id:
                result = copr_chroot
                break
        return result

    def buildroot_pkgs(self, chroot):
        """
        Return packages in minimal buildroot for given chroot.
        """

        result = ""
        # this is ugly as user can remove chroot after he submit build, but
        # lets call this feature
        copr_chroot = self.check_copr_chroot(chroot)
        if copr_chroot:
            result = copr_chroot.buildroot_pkgs
        return result

    @property
    def modified_chroots(self):
        """
        Return list of chroots which has been modified
        """
        modified_chroots = []
        for chroot in self.active_chroots:
            if self.buildroot_pkgs(chroot):
                modified_chroots.append(chroot)
        return modified_chroots
Beispiel #9
0
class User(db.Model, helpers.Serializer):
    """
    Represents user of the copr frontend
    """

    # PK;  TODO: the 'username' could be also PK
    id = db.Column(db.Integer, primary_key=True)

    # unique username
    username = db.Column(db.String(100), nullable=False, unique=True)

    # email
    mail = db.Column(db.String(150), nullable=False)

    # optional timezone
    timezone = db.Column(db.String(50), nullable=True)

    # is this user proven? proven users can modify builder memory and
    # timeout for single builds
    proven = db.Column(db.Boolean, default=False)

    # is this user admin of the system?
    admin = db.Column(db.Boolean, default=False)

    # stuff for the cli interface
    api_login = db.Column(db.String(40), nullable=False, default="abc")
    api_token = db.Column(db.String(40), nullable=False, default="abc")
    api_token_expiration = db.Column(db.Date,
                                     nullable=False,
                                     default=datetime.date(2000, 1, 1))

    @property
    def name(self):
        """
        Return the short username of the user, e.g. bkabrda
        """

        return self.username

    def permissions_for_copr(self, copr):
        """
        Get permissions of this user for the given copr.
        Caches the permission during one request,
        so use this if you access them multiple times
        """

        if not hasattr(self, "_permissions_for_copr"):
            self._permissions_for_copr = {}
        if copr.name not in self._permissions_for_copr:
            self._permissions_for_copr[copr.name] = (
                CoprPermission.query.filter_by(user=self).filter_by(
                    copr=copr).first())
        return self._permissions_for_copr[copr.name]

    def can_build_in(self, copr):
        """
        Determine if this user can build in the given copr.
        """

        can_build = False
        if copr.owner == self:
            can_build = True
        if (self.permissions_for_copr(copr)
                and self.permissions_for_copr(copr).copr_builder
                == helpers.PermissionEnum("approved")):

            can_build = True

        return can_build

    def can_edit(self, copr):
        """
        Determine if this user can edit the given copr.
        """

        can_edit = False
        if copr.owner == self:
            can_edit = True
        if (self.permissions_for_copr(copr)
                and self.permissions_for_copr(copr).copr_admin
                == helpers.PermissionEnum("approved")):

            can_edit = True

        return can_edit

    @property
    def serializable_attributes(self):
        # enumerate here to prevent exposing credentials
        return ["id", "name"]

    @property
    def coprs_count(self):
        """
        Get number of coprs for this user.
        """

        return (Copr.query.filter_by(owner=self).filter_by(
            deleted=False).count())

    @property
    def gravatar_url(self):
        """
        Return url to libravatar image.
        """

        try:
            return libravatar_url(email=self.mail, https=True)
        except IOError:
            return ""
Beispiel #10
0
class BuildChroot(db.Model, helpers.Serializer):
    """
    Representation of Build<->MockChroot relation
    """

    mock_chroot_id = db.Column(db.Integer,
                               db.ForeignKey("mock_chroot.id"),
                               primary_key=True)
    mock_chroot = db.relationship("MockChroot", backref=db.backref("builds"))
    build_id = db.Column(db.Integer,
                         db.ForeignKey("build.id"),
                         primary_key=True)
    build = db.relationship("Build", backref=db.backref("build_chroots"))
    git_hash = db.Column(db.String(40))
    status = db.Column(db.Integer, default=StatusEnum("importing"))

    started_on = db.Column(db.Integer)
    ended_on = db.Column(db.Integer)

    last_deferred = db.Column(db.Integer)

    @property
    def name(self):
        """
        Textual representation of name of this chroot
        """

        return self.mock_chroot.name

    @property
    def state(self):
        """
        Return text representation of status of this build chroot
        """

        if self.status is not None:
            return StatusEnum(self.status)

        return "unknown"

    @property
    def task_id(self):
        return "{}-{}".format(self.build_id, self.name)

    @property
    def import_task_id(self):
        return "{}-{}".format(self.build_id,
                              helpers.chroot_to_branch(self.name))

    @property
    def dist_git_url(self):
        if app.config["DIST_GIT_URL"]:
            return "{}/{}.git/commit/?id={}".format(
                app.config["DIST_GIT_URL"], self.build.package.dist_git_repo,
                self.git_hash)
        return None

    @property
    def import_log_url(self):
        if app.config["COPR_DIST_GIT_LOGS_URL"]:
            return "{}/{}.log".format(app.config["COPR_DIST_GIT_LOGS_URL"],
                                      self.import_task_id)
        return None

    @property
    def result_dir_url(self):
        return "/".join(
            [app.config["BACKEND_BASE_URL"], u"results", self.result_dir])

    @property
    def result_dir(self):
        # hide changes occurred after migration to dist-git
        # if build has defined dist-git, it means that new schema should be used
        # otherwise use older structure

        # old: results/valtri/ruby/fedora-rawhide-x86_64/rubygem-aws-sdk-resources-2.1.11-1.fc24/
        # new: results/asamalik/rh-perl520/epel-7-x86_64/00000187-rh-perl520/

        parts = [self.build.copr.owner_name]

        parts.extend([
            self.build.copr.name,
            self.name,
        ])
        if self.git_hash is not None and self.build.package:
            parts.append(self.build.result_dir_name)
        else:
            parts.append(self.build.src_pkg_name)

        return os.path.join(*parts)

    def __str__(self):
        return "<BuildChroot: {}>".format(self.to_dict())
Beispiel #11
0
class Package(db.Model, helpers.Serializer, CoprSearchRelatedData):
    """
    Represents a single package in a project.
    """
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    # Source of the build: type identifier
    source_type = db.Column(db.Integer,
                            default=helpers.BuildSourceEnum("unset"))
    # Source of the build: description in json, example: git link, srpm url, etc.
    source_json = db.Column(db.Text)
    # True if the package is built automatically via webhooks
    webhook_rebuild = db.Column(db.Boolean, default=False)
    # enable networking during a build process
    enable_net = db.Column(db.Boolean,
                           default=False,
                           server_default="0",
                           nullable=False)

    # @TODO Remove me few weeks after Copr migration
    # Contain status of the Package before migration
    # Normally the `status` is not stored in `Package`. It is computed from `status` variable of `BuildChroot`,
    # but `old_status` has to be stored here, because we migrate whole `package` table, but only succeeded builds.
    # Therefore if `old_status` was in `BuildChroot` we wouldn't be able to know old state of non-succeeded packages
    # even though it would be known before migration.
    old_status = db.Column(db.Integer)

    builds = db.relationship("Build", order_by="Build.id")

    # relations
    copr_id = db.Column(db.Integer, db.ForeignKey("copr.id"))
    copr = db.relationship("Copr", backref=db.backref("packages"))

    @property
    def dist_git_repo(self):
        return "{}/{}".format(self.copr.full_name, self.name)

    @property
    def source_json_dict(self):
        if not self.source_json:
            return {}
        return json.loads(self.source_json)

    @property
    def source_type_text(self):
        return helpers.BuildSourceEnum(self.source_type)

    @property
    def has_source_type_set(self):
        """
        Package's source type (and source_json) is being derived from its first build, which works except
        for "srpm_link" and "srpm_upload" cases. Consider these being equivalent to source_type being unset.
        """
        return self.source_type and self.source_type_text != "srpm_link" and self.source_type_text != "srpm_upload"

    @property
    def dist_git_url(self):
        if app.config["DIST_GIT_URL"]:
            return "{}/{}.git".format(app.config["DIST_GIT_URL"],
                                      self.dist_git_repo)
        return None

    def last_build(self, successful=False):
        for build in reversed(self.builds):
            if not successful or build.state == "succeeded":
                return build
        return None

    def to_dict(self,
                with_latest_build=False,
                with_latest_succeeded_build=False,
                with_all_builds=False):
        package_dict = super(Package, self).to_dict()
        package_dict['source_type'] = helpers.BuildSourceEnum(
            package_dict['source_type'])

        if with_latest_build:
            build = self.last_build(successful=False)
            package_dict['latest_build'] = build.to_dict(
                with_chroot_states=True) if build else None
        if with_latest_succeeded_build:
            build = self.last_build(successful=True)
            package_dict['latest_succeeded_build'] = build.to_dict(
                with_chroot_states=True) if build else None
        if with_all_builds:
            package_dict['builds'] = [
                build.to_dict(with_chroot_states=True)
                for build in reversed(self.builds)
            ]

        return package_dict

    def get_search_related_copr_id(self):
        return self.copr.id
Beispiel #12
0
class User(db.Model, helpers.Serializer):
    """
    Represents user of the copr frontend
    """

    # PK;  TODO: the 'username' could be also PK
    id = db.Column(db.Integer, primary_key=True)

    # unique username
    username = db.Column(db.String(100), nullable=False, unique=True)

    # email
    mail = db.Column(db.String(150), nullable=False)

    # optional timezone
    timezone = db.Column(db.String(50), nullable=True)

    # is this user proven? proven users can modify builder memory and
    # timeout for single builds
    proven = db.Column(db.Boolean, default=False)

    # is this user admin of the system?
    admin = db.Column(db.Boolean, default=False)

    # stuff for the cli interface
    api_login = db.Column(db.String(40), nullable=False, default="abc")
    api_token = db.Column(db.String(40), nullable=False, default="abc")
    api_token_expiration = db.Column(db.Date,
                                     nullable=False,
                                     default=datetime.date(2000, 1, 1))

    # list of groups as retrieved from openid
    openid_groups = db.Column(JSONEncodedDict)

    @property
    def name(self):
        """
        Return the short username of the user, e.g. bkabrda
        """

        return self.username

    def permissions_for_copr(self, copr):
        """
        Get permissions of this user for the given copr.
        Caches the permission during one request,
        so use this if you access them multiple times
        """

        if not hasattr(self, "_permissions_for_copr"):
            self._permissions_for_copr = {}
        if copr.name not in self._permissions_for_copr:
            self._permissions_for_copr[copr.name] = (
                CoprPermission.query.filter_by(user=self).filter_by(
                    copr=copr).first())
        return self._permissions_for_copr[copr.name]

    def can_build_in(self, copr):
        """
        Determine if this user can build in the given copr.
        """
        can_build = False
        if copr.user_id == self.id:
            can_build = True
        if (self.permissions_for_copr(copr)
                and self.permissions_for_copr(copr).copr_builder
                == helpers.PermissionEnum("approved")):

            can_build = True

        # a bit dirty code, here we access flask.session object
        if copr.group is not None and \
                copr.group.fas_name in self.user_teams:
            return True

        return can_build

    @property
    def user_teams(self):
        if self.openid_groups and 'fas_groups' in self.openid_groups:
            return self.openid_groups['fas_groups']
        else:
            return []

    @property
    def user_groups(self):
        return Group.query.filter(Group.fas_name.in_(self.user_teams)).all()

    def can_build_in_group(self, group):
        """
        :type group: Group
        """
        if group.fas_name in self.user_teams:
            return True
        else:
            return False

    def can_edit(self, copr):
        """
        Determine if this user can edit the given copr.
        """

        if copr.user == self or self.admin:
            return True
        if (self.permissions_for_copr(copr)
                and self.permissions_for_copr(copr).copr_admin
                == helpers.PermissionEnum("approved")):

            return True

        if copr.group is not None and \
                copr.group.fas_name in self.user_teams:
            return True

        return False

    @property
    def serializable_attributes(self):
        # enumerate here to prevent exposing credentials
        return ["id", "name"]

    @property
    def coprs_count(self):
        """
        Get number of coprs for this user.
        """

        return (Copr.query.filter_by(user=self).filter_by(
            deleted=False).filter_by(group_id=None).count())

    @property
    def gravatar_url(self):
        """
        Return url to libravatar image.
        """

        try:
            return libravatar_url(email=self.mail, https=True)
        except IOError:
            return ""
Beispiel #13
0
class Copr(db.Model, helpers.Serializer, CoprSearchRelatedData):
    """
    Represents a single copr (private repo with builds, mock chroots, etc.).
    """

    id = db.Column(db.Integer, primary_key=True)
    # name of the copr, no fancy chars (checked by forms)
    name = db.Column(db.String(100), nullable=False)
    homepage = db.Column(db.Text)
    contact = db.Column(db.Text)
    # string containing urls of additional repos (separated by space)
    # that this copr will pull dependencies from
    repos = db.Column(db.Text)
    # time of creation as returned by int(time.time())
    created_on = db.Column(db.Integer)
    # description and instructions given by copr owner
    description = db.Column(db.Text)
    instructions = db.Column(db.Text)
    deleted = db.Column(db.Boolean, default=False)
    playground = db.Column(db.Boolean, default=False)

    # should copr run `createrepo` each time when build packages are changed
    auto_createrepo = db.Column(db.Boolean, default=True)

    # relations
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    user = db.relationship("User", backref=db.backref("coprs"))
    group_id = db.Column(db.Integer, db.ForeignKey("group.id"))
    group = db.relationship("Group", backref=db.backref("groups"))
    mock_chroots = association_proxy("copr_chroots", "mock_chroot")
    forked_from_id = db.Column(db.Integer, db.ForeignKey("copr.id"))
    forked_from = db.relationship("Copr",
                                  remote_side=id,
                                  backref=db.backref("forks"))

    # a secret to be used for webhooks authentication
    webhook_secret = db.Column(db.String(100))

    # enable networking for the builds by default
    build_enable_net = db.Column(db.Boolean,
                                 default=True,
                                 server_default="1",
                                 nullable=False)

    unlisted_on_hp = db.Column(db.Boolean, default=False, nullable=False)

    # information for search index updating
    latest_indexed_data_update = db.Column(db.Integer)

    # builds and the project are immune against deletion
    persistent = db.Column(db.Boolean,
                           default=False,
                           nullable=False,
                           server_default="0")

    __mapper_args__ = {"order_by": created_on.desc()}

    @property
    def is_a_group_project(self):
        """
        Return True if copr belongs to a group
        """
        return self.group_id is not None

    @property
    def owner(self):
        """
        Return owner (user or group) of this copr
        """
        return self.group if self.is_a_group_project else self.user

    @property
    def owner_name(self):
        """
        Return @group.name for a copr owned by a group and user.name otherwise
        """
        return self.group.at_name if self.is_a_group_project else self.user.name

    @property
    def repos_list(self):
        """
        Return repos of this copr as a list of strings
        """
        return self.repos.split()

    @property
    def active_chroots(self):
        """
        Return list of active mock_chroots of this copr
        """

        return filter(lambda x: x.is_active, self.mock_chroots)

    @property
    def active_copr_chroots(self):
        """
        :rtype: list of CoprChroot
        """
        return [c for c in self.copr_chroots if c.is_active]

    @property
    def active_chroots_sorted(self):
        """
        Return list of active mock_chroots of this copr
        """

        return sorted(self.active_chroots, key=lambda ch: ch.name)

    @property
    def active_chroots_grouped(self):
        """
        Return list of active mock_chroots of this copr
        """

        chroots = [("{} {}".format(c.os_release, c.os_version), c.arch)
                   for c in self.active_chroots_sorted]
        output = []
        for os, chs in itertools.groupby(chroots, operator.itemgetter(0)):
            output.append((os, [ch[1] for ch in chs]))

        return output

    @property
    def build_count(self):
        """
        Return number of builds in this copr
        """

        return len(self.builds)

    @property
    def disable_createrepo(self):

        return not self.auto_createrepo

    @disable_createrepo.setter
    def disable_createrepo(self, value):

        self.auto_createrepo = not bool(value)

    @property
    def modified_chroots(self):
        """
        Return list of chroots which has been modified
        """
        modified_chroots = []
        for chroot in self.copr_chroots:
            if chroot.buildroot_pkgs and chroot.is_active:
                modified_chroots.append(chroot)
        return modified_chroots

    def is_release_arch_modified(self, name_release, arch):
        if "{}-{}".format(name_release, arch) in \
                [chroot.name for chroot in self.modified_chroots]:
            return True
        return False

    @property
    def full_name(self):
        return "{}/{}".format(self.owner_name, self.name)

    @property
    def repo_name(self):
        return "{}-{}".format(self.owner_name, self.name)

    @property
    def repo_url(self):
        return "/".join(
            [app.config["BACKEND_BASE_URL"], u"results", self.full_name])

    @property
    def modules_url(self):
        return "/".join([self.repo_url, "modules"])

    @property
    def repo_id(self):
        if self.is_a_group_project:
            return "group_{}-{}".format(self.group.name, self.name)
        else:
            return "{}-{}".format(self.user.name, self.name)

    def to_dict(self, private=False, show_builds=True, show_chroots=True):
        result = {}
        for key in ["id", "name", "description", "instructions"]:
            result[key] = str(copy.copy(getattr(self, key)))
        result["owner"] = self.owner_name
        return result

    @property
    def still_forking(self):
        return bool(
            Action.query.filter(
                Action.result == helpers.BackendResultEnum("waiting")).filter(
                    Action.action_type == helpers.ActionTypeEnum("fork")).
            filter(Action.new_value == self.full_name).all())

    def get_search_related_copr_id(self):
        return self.id
Beispiel #14
0
class Copr(db.Model, helpers.Serializer):
    """
    Represents a single copr (private repo with builds, mock chroots, etc.).
    """

    id = db.Column(db.Integer, primary_key=True)
    # name of the copr, no fancy chars (checked by forms)
    name = db.Column(db.String(100), nullable=False)
    homepage = db.Column(db.Text)
    contact = db.Column(db.Text)
    # string containing urls of additional repos (separated by space)
    # that this copr will pull dependencies from
    repos = db.Column(db.Text)
    # time of creation as returned by int(time.time())
    created_on = db.Column(db.Integer)
    # description and instructions given by copr owner
    description = db.Column(db.Text)
    instructions = db.Column(db.Text)
    deleted = db.Column(db.Boolean, default=False)
    playground = db.Column(db.Boolean, default=False)

    # should copr run `createrepo` each time when build packages are changed
    auto_createrepo = db.Column(db.Boolean, default=True)

    # relations
    owner_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    owner = db.relationship("User", backref=db.backref("coprs"))
    group_id = db.Column(db.Integer, db.ForeignKey("group.id"))
    group = db.relationship("Group", backref=db.backref("groups"))
    mock_chroots = association_proxy("copr_chroots", "mock_chroot")

    # a secret to be used for webhooks authentication
    webhook_secret = db.Column(db.String(100))

    # enable networking for the builds by default
    build_enable_net = db.Column(db.Boolean,
                                 default=True,
                                 server_default="1",
                                 nullable=False)

    __mapper_args__ = {"order_by": created_on.desc()}

    @property
    def is_a_group_project(self):
        return self.group_id is not None

    @property
    def owner_name(self):
        return self.owner.name

    @property
    def group_name(self):
        return self.group.name

    @property
    def repos_list(self):
        """
        Return repos of this copr as a list of strings
        """
        return self.repos.split()

    @property
    def active_chroots(self):
        """
        Return list of active mock_chroots of this copr
        """

        return filter(lambda x: x.is_active, self.mock_chroots)

    @property
    def active_copr_chroots(self):
        """
        :rtype: list of CoprChroot
        """
        return [c for c in self.copr_chroots if c.is_active]

    @property
    def active_chroots_sorted(self):
        """
        Return list of active mock_chroots of this copr
        """

        return sorted(self.active_chroots, key=lambda ch: ch.name)

    @property
    def active_chroots_grouped(self):
        """
        Return list of active mock_chroots of this copr
        """

        chroots = [("{} {}".format(c.os_release, c.os_version), c.arch)
                   for c in self.active_chroots_sorted]
        output = []
        for os, chs in itertools.groupby(chroots, operator.itemgetter(0)):
            output.append((os, [ch[1] for ch in chs]))

        return output

    @property
    def build_count(self):
        """
        Return number of builds in this copr
        """

        return len(self.builds)

    @property
    def disable_createrepo(self):

        return not self.auto_createrepo

    @disable_createrepo.setter
    def disable_createrepo(self, value):

        self.auto_createrepo = not bool(value)

    @property
    def modified_chroots(self):
        """
        Return list of chroots which has been modified
        """
        modified_chroots = []
        for chroot in self.copr_chroots:
            if chroot.buildroot_pkgs and chroot.is_active:
                modified_chroots.append(chroot)
        return modified_chroots

    def is_release_arch_modified(self, name_release, arch):
        if "{}-{}".format(name_release, arch) in \
                [chroot.name for chroot in self.modified_chroots]:
            return True
        return False

    @property
    def full_name(self):
        if self.is_a_group_project:
            return "@{}/{}".format(self.group.name, self.name)
        else:
            return "{}/{}".format(self.owner.username, self.name)

    @property
    def repo_name(self):
        if self.is_a_group_project:
            return "@{}-{}".format(self.group.name, self.name)
        else:
            return "{}-{}".format(self.owner.username, self.name)

    @property
    def repo_id(self):
        if self.is_a_group_project:
            return "group_{}-{}".format(self.group.name, self.name)
        else:
            return "{}-{}".format(self.owner.username, self.name)

    def to_dict(self, private=False, show_builds=True, show_chroots=True):
        result = {}
        for key in ["id", "name", "description", "instructions"]:
            result[key] = str(copy.copy(getattr(self, key)))
        result["owner"] = self.owner.name
        return result