Example #1
0
 def add_package_to_lists(self, pkg: Pkg, index_updater_events: dict):
     """
     Adds the package information to database
     
     Args:
         pkg (Pkg): the package
         index_updater_events (dict): events for index updater
     """
     if not os.path.isdir(Env.packages_lists('/' + pkg.data['name'])):
         os.mkdir(Env.packages_lists('/' + pkg.data['name']))
     lists_path = Env.packages_lists('/' + pkg.data['name'] + '/' +
                                     pkg.data['version'] + '-' +
                                     pkg.data['arch'])
     try:
         lists_f = open(lists_path, 'r')
         old_repo = json.loads(lists_f.read())['repo']
         lists_f.close()
     except:
         old_repo = 'Local'
     try:
         lists_f = open(lists_path, 'r')
         old_file_path = json.loads(lists_f.read())['file_path']
         lists_f.close()
     except:
         old_file_path = False
     try:
         lists_f = open(lists_path, 'r')
         old_file_sha256 = json.loads(lists_f.read())['file_sha256']
         lists_f.close()
     except:
         old_file_sha256 = False
     try:
         lists_f = open(lists_path, 'r')
         old_file_md5 = json.loads(lists_f.read())['file_md5']
         lists_f.close()
     except:
         old_file_md5 = False
     lists_f = open(lists_path, 'w')
     pkg.data['repo'] = old_repo
     if old_file_path != False:
         pkg.data['file_path'] = old_file_path
     tmp_pkg_data = pkg.data
     if old_file_md5:
         tmp_pkg_data['file_md5'] = old_file_md5
     if old_file_sha256:
         tmp_pkg_data['file_sha256'] = old_file_sha256
     tmp_pkg_data['files'] = [
         '/' + member[6:] for member in pkg.members()
         if member[:6] == 'files/'
     ]
     lists_f.write(json.dumps(tmp_pkg_data))
     lists_f.close()
     ListUpdater.update_indexes(index_updater_events)
     ListUpdater.index_reverse_depends_and_conflicts(pkg)
Example #2
0
def update_indexes(events: dict):
    """
    This function loads available versions of a package and index them in index file
    and do this action for all of packages in lists.

    Args:
        events: (dict) the `events` argument should be a dictonary from functions. this will use to handle errors
                for example if some thing went wrong, the spesific function in events
                will run.
                events:
                - cannot_read_file: if in this process, an error happened while reading a file, this will run with file path arg
                - invalid_json_data: if json content of a file is curropt, this will run with file path and content args
    """

    require_root_permission()

    for pkg in os.listdir(Env.packages_lists()):
        pkg_index = {}
        if os.path.isdir(Env.packages_lists('/' + pkg)):
            for version in os.listdir(Env.packages_lists('/' + pkg)):
                if version not in [
                        'index', 'reverse_depends', 'reverse_conflicts'
                ]:
                    if os.path.isfile(
                            Env.packages_lists('/' + pkg + '/' + version)):
                        content = None
                        try:
                            f = open(
                                Env.packages_lists('/' + pkg + '/' + version),
                                'r')
                            content = f.read()
                        except:
                            events['cannot_read_file'](
                                Env.packages_lists('/' + pkg + '/' + version))

                        if content != None:
                            try:
                                content_json = json.loads(content)
                                try:
                                    tmp = pkg_index[content_json['arch']]
                                    del tmp
                                except:
                                    pkg_index[content_json['arch']] = []
                                pkg_index[content_json['arch']].append(
                                    content_json['version'])
                            except:
                                events['invalid_json_data'](
                                    Env.packages_lists('/' + pkg + '/' +
                                                       version), content)
        # write generated index to index file
        f_index = open(Env.packages_lists('/' + pkg + '/index'), 'w')
        f_index.write(json.dumps(pkg_index))
        f_index.close()
Example #3
0
    def run(self):
        """ Run test """
        self.assert_equals(
            self.run_command('pkg', [
                'install',
                'repository/test-repository/simple-test-package.cati'
            ]), 0)

        self.assert_true(os.path.isfile(self.env('/usr/bin/cati-testpkga')))

        self.assert_equals(
            self.run_command('pkg', [
                'install',
                'repository/test-repository/simple-test-package.cati'
            ]), 0)

        self.assert_true(os.path.isfile(self.env('/usr/bin/cati-testpkga')))

        pkg = Pkg.load_from_index(
            json.loads(
                open(Env.packages_lists('/testpkga/index'), 'r').read()),
            'testpkga')
        self.assert_equals(pkg.installed(), '1.0')

        self.refresh_env()

        self.assert_equals(
            self.run_command('pkg', [
                'install',
                'repository/test-repository/testpkg-with-file-conflict-a.cati',
            ]), 0)

        self.assert_true(
            os.path.isfile(self.env() +
                           '/etc/testpkg-with-file-conflict/test.txt'))

        self.refresh_env()

        os.mkdir(self.env() + '/app')

        self.assert_equals(
            self.run_command('pkg', [
                'install',
                'repository/test-repository/testpkg-with-file-conflict-a.cati',
                '--target=/app'
            ]), 0)

        self.assert_true(not os.path.isfile(
            self.env() + '/etc/testpkg-with-file-conflict/test.txt'))
        self.assert_true(
            os.path.isfile(self.env() +
                           '/app/etc/testpkg-with-file-conflict/test.txt'))
Example #4
0
    def run(self):
        """ Run command """

        RootRequired.require_root_permission()

        pr.p('Loading packages list...')
        pr.p('========================')

        loaded_packages = []

        for argument in self.arguments:
            arg_parts = argument.split('=')
            if len(arg_parts) == 1:
                # load last version as default
                pkg = Pkg.load_last(argument)
            else:
                # load specify version
                pkg = Pkg.load_version(arg_parts[0], arg_parts[1])
                if pkg == 1:
                    pkg = False
                elif pkg == 2:
                    self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red)
                    continue
                else:
                    pkg.only_specify_version = True
            if pkg:
                try:
                    pkg.only_specify_version
                except:
                    pkg.only_specify_version = False
                if pkg.installed():
                    if not pkg.only_specify_version:
                        self.message('package "' + argument + '" is installed. cannot forget installed packages' + ansi.reset, before=ansi.red)
                        continue
                    else:
                        if pkg.installed() == pkg.data['version']:
                            self.message('package ' + argument + ' (' + pkg.data['version'] + ') is installed. cannot forget installed packages' + ansi.reset, before=ansi.red)
                            continue
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red)

        if not loaded_packages:
            return 1

        # forget loaded packages
        for pkg in loaded_packages:
            if not pkg.only_specify_version:
                # forget all of package versions
                shutil.rmtree(Env.packages_lists('/' + pkg.data['name']))
                pr.p('Package ' + pkg.data['name'] + ' was forgoten successfully')
            else:
                files = glob.glob(Env.packages_lists('/' + pkg.data['name'] + '/' + pkg.data['version'] + '-*'))
                for f in files:
                    if not '-' in f[len(Env.packages_lists('/' + pkg.data['name'] + '/' + pkg.data['version'] + '-')):]:
                        os.remove(f)
                pr.p('Version ' + pkg.data['version'] + ' of package ' + pkg.data['name'] + ' was forgoten successfully')
            try:
                if len(os.listdir(Env.packages_lists('/' + pkg.data['name']))) <= 1:
                    shutil.rmtree(Env.packages_lists('/' + pkg.data['name']))
            except:
                pass

        ListUpdater.update_indexes({
            'cannot_read_file': self.empty_method_for_event,
            'invalid_json_data': self.empty_method_for_event,
        })
Example #5
0
def index_reverse_depends_and_conflicts(pkg: Pkg):
    """
    Packages have `depends` and `conflicts`
    But also they have `Reverse` depends and conflicts
    Reverse d/c should be indexed because loading them real time is so big process
    We index them in a place, and when a package is added/changed, this function should be called

    Args:
        pkg (Pkg): changed/added package (reverse c/d will be set for that packages this package is related to them)
    """
    # load the packages
    depend_pkgs = []
    conflict_pkgs = []
    for depend in pkg.get_depends():
        query_parts = Pkg.check_state(depend, only_parse=True)
        for depth1 in query_parts:
            for depth2 in depth1:
                depend_pkgs.append(depth2[0])
    for conflict in pkg.get_conflicts():
        query_parts = Pkg.check_state(conflict, only_parse=True)
        for depth1 in query_parts:
            for depth2 in depth1:
                conflict_pkgs.append(depth2[0])

    # set reverse depends/conflicts for found packages
    for p in depend_pkgs:
        f_path = Env.packages_lists('/' + p + '/reverse_depends')
        current_list = None
        try:
            if not os.path.isdir(Env.packages_lists('/' + p)):
                os.mkdir(Env.packages_lists('/' + p))
            if not os.path.isfile(f_path):
                current_list = []
            else:
                f = open(f_path, 'r')
                current_list = [
                    item.strip() for item in f.read().strip().split('\n')
                    if item.strip() != ''
                ]
                f.close()
            if not pkg.data['name'] in current_list:
                current_list.append(pkg.data['name'])
            # write new list
            new_list_str = ''
            for item in current_list:
                new_list_str += item + '\n'
            new_list_str = new_list_str.strip()
            f = open(f_path, 'w')
            f.write(new_list_str)
            f.close()
        except:
            pass
    for p in conflict_pkgs:
        f_path = Env.packages_lists('/' + p + '/reverse_conflicts')
        current_list = None
        try:
            if not os.path.isdir(Env.packages_lists('/' + p)):
                os.mkdir(Env.packages_lists('/' + p))
            if not os.path.isfile(f_path):
                current_list = []
            else:
                f = open(f_path, 'r')
                current_list = [
                    item.strip() for item in f.read().strip().split('\n')
                    if item.strip() != ''
                ]
                f.close()
            if not pkg.data['name'] in current_list:
                current_list.append(pkg.data['name'])
            # write new list
            new_list_str = ''
            for item in current_list:
                new_list_str += item + '\n'
            new_list_str = new_list_str.strip()
            f = open(f_path, 'w')
            f.write(new_list_str)
            f.close()
        except:
            pass
Example #6
0
    def run(self):
        """ Run command """

        RootRequired.require_root_permission()

        if not self.is_quiet():
            pr.p('Loading repositories list...')
        repos = Repo.get_list()
        ReposListErrorShower.show(repos)

        if not self.is_quiet():
            pr.p('Prepairing to update repos...')
        orig_repos = []
        for repo in repos:
            if repo.successful_loaded:
                if repo.test():
                    if not repo.is_disable:
                        orig_repos.append(repo)
                    else:
                        if not self.is_quiet():
                            self.message('Warning: ignoring repository "' +
                                         repo.name +
                                         '" because this is disable')
                else:
                    pr.e(ansi.red + 'Cannot make connection to repo "' +
                         repo.full_string + '"' + ansi.reset)

        if not self.is_quiet():
            pr.p('Updating repositories...')
            pr.p('=============================')

        # downloaded repos data files paths
        downloaded_paths = []

        # update repos
        for repo in list(reversed(orig_repos)):
            if not self.is_quiet():
                pr.p('Fetching ' + repo.name + ' (' + repo.url + ') data...')
            data = repo.get_data(download_event=self.download_event)
            if type(data) == int:
                pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' +
                     repo.url + '): error code ' + str(data) + ansi.reset)
            elif isinstance(data, Exception):
                pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' +
                     repo.url + '): ' + str(data) + ansi.reset)
            else:
                # validate data
                try:
                    tmp = json.loads(data)
                    # save data in an file
                    path = Env.cache_dir('/' + repo.name + '-' +
                                         str(time.time()) +
                                         str(random.random())) + '.json'
                    f = open(path, 'w')
                    f.write(data)
                    f.close()
                    downloaded_paths.append(path)
                except:
                    pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' +
                         repo.url + '): invalid json data recived' +
                         ansi.reset)

        if not self.is_quiet():
            pr.p('Updating packages list...')

        # load downloaded data
        packages = []
        for path in downloaded_paths:
            f = open(path, 'r')
            data = f.read().strip()
            f.close()
            items = json.loads(data)
            for item in items:
                if PackageJsonValidator.validate(item):
                    packages.append(item)
                else:
                    pass

        for pkg in packages:
            if PackageJsonValidator.validate(pkg):
                if self.is_verbose():
                    pr.p('adding ' + pkg['name'] + ':' + pkg['version'] + ':' +
                         pkg['arch'] + '...')
                # write package on list
                if not os.path.isdir(Env.packages_lists('/' + pkg['name'])):
                    os.mkdir(Env.packages_lists('/' + pkg['name']))
                try:
                    f = open(
                        Env.packages_lists('/' + pkg['name'] + '/' +
                                           pkg['version'] + '-' + pkg['arch']),
                        'w')
                    f.write(json.dumps(pkg))
                    f.close()
                    ListUpdater.index_reverse_depends_and_conflicts(Pkg(pkg))
                except:
                    pr.e(ansi.red + 'error while adding ' + pkg['name'] + ':' +
                         pkg['version'] + ':' + pkg['arch'] + ansi.reset)
            else:
                if self.is_verbose():
                    pr.p(ansi.yellow +
                         'invalid json data in an item. ignored...' +
                         ansi.reset)

        if self.is_quiet():
            pr.p('Finishing update...')
        ListUpdater.update_indexes({
            'cannot_read_file': self.empty_method,
            'invalid_json_data': self.empty_method,
        })

        pr.p(ansi.green + 'Done.' + ansi.reset)