コード例 #1
0
ファイル: Calculator.py プロジェクト: parsampsh/cati
    def handle_install_reverse_depends(self):
        """ Adds installable packages reverse depends to install list """
        new_to_remove = []
        i = 0
        while i < len(self.to_install):
            reverse_depends = self.to_install[i].get_reverse_depends()
            for dep in reverse_depends:
                if dep.installed():
                    dep = Pkg.load_version(dep.data['name'], dep.installed())
                    for tmp_dep in dep.get_depends():
                        result = Pkg.check_state(
                            tmp_dep,
                            virtual={
                                'install': [[
                                    self.to_install[i].data['name'],
                                    self.to_install[i].data['version']
                                ]],
                            })
                        if not result:
                            a = 0
                            added = False
                            while a < len(self.to_remove):
                                if self.to_remove[a].data['name'] == dep.data[
                                        'name']:
                                    added = True
                                a += 1
                            if not added:
                                new_to_remove.append(dep)
            i += 1

        if new_to_remove:
            self.remove(new_to_remove)
コード例 #2
0
ファイル: ListCommand.py プロジェクト: parsampsh/cati
    def show_once(self, package: Pkg):
        """
        show once item in loaded packages list
        """
        if self.has_option('-q') or self.has_option('--quiet'):
            pr.p(package.data['name'])
            return
        output = ansi.green + package.data[
            'name'] + ansi.reset + '/' + ansi.yellow + package.data[
                'version'] + ansi.reset
        if package.installed():
            if package.is_installed_manual(package.data['name']):
                output += '/Installed-Manual:' + ansi.blue + package.installed(
                ).strip() + ansi.reset
            else:
                output += '/Installed:' + ansi.blue + package.installed(
                ).strip() + ansi.reset
        output += '/[' + package.data['repo'] + ']'

        # if verbose output wanted, show first line of description
        if self.is_verbose():
            try:
                description_summary = package.data['description'].split(
                    '\n')[0]
                if description_summary != '':
                    output += '/ ' + ansi.header + description_summary + ansi.reset
            except:
                pass

        pr.p(output)
コード例 #3
0
    def find_unused_packages(self):
        """ finds unused packages """
        all_packages = Pkg.all_list()['list']

        for pkg in all_packages:
            try:
                if Pkg.is_installed(pkg.data['name']):
                    if not Pkg.is_installed_manual(pkg.data['name']):
                        has_any_reverse_depends = False
                        reverse_depends = Pkg.load_version(
                            pkg.data['name'],
                            Pkg.installed_version(
                                pkg.data['name'])).get_reverse_depends()
                        for rdep in reverse_depends:
                            if rdep.installed():
                                rdep_is_in_unused_packages = False
                                for upkg in self.unused_packages:
                                    if upkg.data['name'] == rdep.data['name']:
                                        rdep_is_in_unused_packages = True
                                if not rdep_is_in_unused_packages:
                                    has_any_reverse_depends = True
                        if not has_any_reverse_depends:
                            self.unused_packages.append(pkg)
            except:
                pass
コード例 #4
0
ファイル: Installer.py プロジェクト: parsampsh/cati
    def run_script(self, script_name: str, script_path=None):
        """
        runs an script in the package (only install scripts)

        Args:
            script_name (str): name of that script you want to run
            script_path (str, None): you can change the default path of script file with this argument

        Raises:
            dotcati.exceptions.PackageScriptError: when script returns non-zero exit code
                (exit code will put in `error_code` attribute of exception object)
        """
        if script_path == None:
            script_path = self.extracted_package_dir + '/scripts/' + script_name
        if os.path.isfile(script_path):
            # script exists, run script
            os.system('chmod +x "' + script_path + '"')
            # run script and pass old version of package (if currently installed)
            old_version = ''
            try:
                old_version = self.old_version
            except:
                if Pkg.is_installed(self.pkg.data['name']):
                    self.old_version = '"' + Pkg.installed_version(self.pkg.data['name']) + '"'
                    old_version = self.old_version
            result = os.system(script_path + ' ' + old_version)
            if result != 0:
                tmp = PackageScriptError("script " + script_name + ' returned non-zero code ' + str(result))
                tmp.error_code = result
                raise tmp
コード例 #5
0
    def run(self):
        """ Run command """

        if not self.is_quiet():
            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)
            elif len(arg_parts) == 2:
                # 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:
                # load specify version and specify arch
                pkg = Pkg.load_version(arg_parts[0], arg_parts[1], arg_parts[2])
                if pkg == 1:
                    pkg = False
                elif pkg == 2:
                    self.message('package "' + arg_parts[0] + '" has not version or arch "' + arg_parts[1] + ':' + arg_parts[2] + '"' + ansi.reset, before=ansi.red)
                    continue
            if pkg:
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red)

        if not loaded_packages:
            return 1

        # download loaded packages
        is_any_success = False
        output_path = self.option_value('--output')
        for pkg in loaded_packages:
            if len(loaded_packages) > 1:
                tmp = self.download_once(pkg)
            else:
                tmp = self.download_once(pkg, output_path)
            if tmp:
                is_any_success = True

        if not is_any_success:
            return 1
コード例 #6
0
ファイル: test_channel_system.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run test """
        repo_path = os.getcwd() + '/repository/test-channels'

        self.assert_equals(self.run_command('repo', ['--scan', repo_path]), 0)

        repo = 'file://' + os.getcwd(
        ) + '/repository/test-channels arch=all pkg=cati'
        self.assert_equals(self.run_command('repo', ['--add', repo]), 0)
        self.assert_equals(self.run_command('update'), 0)
        pkg = Pkg.load_last('channelpkg')
        versions = pkg.get_versions_list()
        self.assert_equals(len(versions), 10)

        self.refresh_env()

        repo = 'file://' + os.getcwd(
        ) + '/repository/test-channels arch=all pkg=cati channel=dev'
        self.assert_equals(self.run_command('repo', ['--add', repo]), 0)
        self.assert_equals(self.run_command('update'), 0)
        pkg = Pkg.load_last('channelpkg')
        versions = pkg.get_versions_list()
        self.assert_equals(len(versions), 2)

        self.refresh_env()

        repo = 'file://' + os.getcwd(
        ) + '/repository/test-channels arch=all pkg=cati channel=dev,alpha'
        self.assert_equals(self.run_command('repo', ['--add', repo]), 0)
        self.assert_equals(self.run_command('update'), 0)
        pkg = Pkg.load_last('channelpkg')
        versions = pkg.get_versions_list()
        self.assert_equals(len(versions), 5)

        # test upgrade

        self.assert_equals(self.run_command('install', ['-y', 'channelpkg']),
                           0)
        pkg = Pkg.load_last('channelpkg')
        self.assert_equals(pkg.installed(), '1.0-alpha2')

        repo = 'file://' + os.getcwd(
        ) + '/repository/test-channels arch=all pkg=cati channel=release'
        self.assert_equals(self.run_command('repo', ['--add', repo]), 0)
        self.assert_equals(self.run_command('update'), 0)

        self.assert_equals(self.run_command('upgrade', ['-y']), 0)
        pkg = Pkg.load_last('channelpkg')
        self.assert_equals(pkg.installed(), '1.0')
コード例 #7
0
ファイル: Calculator.py プロジェクト: parsampsh/cati
    def refresh_lists(self):
        """ Refresh packages list and sync them with depends and conflicts """
        # sync versions
        i = 0
        while i < len(self.to_remove):
            self.to_remove[i] = Pkg.load_version(
                self.to_remove[i].data['name'], self.to_remove[i].installed())
            i += 1
        i = 0
        while i < len(self.to_install):
            wv = self.to_install[i].wanted_version
            im = self.to_install[i].is_manual
            self.to_install[i] = Pkg.load_version(
                self.to_install[i].data['name'],
                self.to_install[i].wanted_version)
            self.to_install[i].wanted_version = wv
            self.to_install[i].is_manual = im
            i += 1

        # remove repeated lists in to_remove list
        a = 0
        while a < len(self.to_remove):
            b = 0
            while b < len(self.to_remove):
                if a != b:
                    if self.to_remove[a].data['name'] == self.to_remove[
                            b].data['name']:
                        self.to_remove.pop(b)
                        a -= 1
                        b -= 1
                b += 1
            a += 1

        # sync to_remove list
        new_to_remove = []
        for item in self.to_remove:
            # load reverse dependnecy of current package and add them to list
            reverse_depends = item.get_reverse_depends()
            for rd in reverse_depends:
                if rd.installed():
                    if not rd.data['name'] in [
                            tmp.data['name'] for tmp in self.to_remove
                    ]:
                        new_to_remove.append(rd)
        if new_to_remove:
            self.remove(new_to_remove)

        self.handle_install_depends()
        self.handle_install_conflicts()
コード例 #8
0
ファイル: test_update_system.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run test """
        self.assert_equals(self.run_command('update'), 0)

        self.assert_equals(
            self.run_command('repo', ['--scan', 'repository/test-repository']),
            0)

        f = open(self.env() + '/etc/cati/repos.list', 'w')
        f.write('''
        file://''' + os.getcwd() +
                '''/repository/test-repository name=main arch=i386 pkg=cati
        ''')
        f.close()

        self.assert_equals(len(Pkg.all_list()['list']), 0)

        self.assert_equals(self.run_command('update'), 0)

        try:
            pkg_count = len(Pkg.all_list()['list'])
            self.assert_true(pkg_count >= 9 and pkg_count <= 13)
        except:
            print('Packages count:', pkg_count)
            raise

        f = open(self.env() + '/etc/cati/repos.list.d/repo-b', 'w')
        f.write('''
        file://''' + os.getcwd() +
                '''/repository/test-repository name=main-2 arch=all pkg=cati
        ''')
        f.close()

        try:
            pkg_count = len(Pkg.all_list()['list'])
            self.assert_true(pkg_count >= 9 and pkg_count <= 13)
        except:
            print('Packages count:', pkg_count)
            raise

        self.assert_equals(self.run_command('update'), 0)

        try:
            pkg_count = len(Pkg.all_list()['list'])
            self.assert_true(pkg_count >= 15 and pkg_count <= 19)
        except:
            print('Packages count:', pkg_count)
            raise
コード例 #9
0
    def read(self):
        """
        Load package information on object.
        
        This method has not arg or output, just loads some information of package to this object.

        Raises:
            Exception: will raise normal Exception when package json data is invalid
                       (validated by dotcati.PackageJsonValidator.validate())
        """
        self.data = self.info()
        if not PackageJsonValidator.validate(self.data):
            raise
        # try to compare version for version validation
        Pkg.compare_version(self.data['version'], '0.0.0')
        self.data['version'] = self.data['version'].strip()
コード例 #10
0
    def run(self):
        """ Run command """

        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
            if pkg:
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset,
                             before=ansi.red)

        if not loaded_packages:
            return 1

        # show loaded packages
        for pkg in loaded_packages:
            if self.has_option('--versions'):
                versions_list = pkg.get_versions_list()
                pr.p(pkg.data['name'] + ':')
                for ver in versions_list:
                    pr.p(' ' + ver[0] + ':' + ver[1])
            else:
                PackageShower.show(pkg.data)
            if len(loaded_packages) > 1:
                pr.p('---------------------')
コード例 #11
0
    def run(self):
        """ Run test """
        self.assert_equals(
            self.run_command(
                'pkg',
                ['install', 'repository/test-repository/testpkgc-2.0.cati']),
            0)

        state_f = open(Env.state_file(), 'w')
        state_f.write(f'install%testpackage1%1.0%amd64\nremove%anotherpackage')
        state_f.close()

        self.assert_equals(self.run_command('remove', [
            'testpkgc',
            '-y',
        ]), 1)

        self.assert_equals(
            self.run_command(
                'pkg',
                ['install', 'repository/test-repository/testpkgc-2.0.cati']),
            1)

        # tests for cli `state` command
        self.assert_equals(self.run_command('state'), 1)
        self.assert_equals(self.run_command('state', ['--abort', '-y']), 0)
        self.assert_equals(self.run_command('state'), 0)

        self.refresh_env()

        self.assert_equals(
            self.run_command(
                'pkg',
                ['install', 'repository/test-repository/testpkgc-2.0.cati']),
            0)
        self.assert_true(Pkg.is_installed('testpkgc'))
        state_f = open(Env.state_file(), 'w')
        state_f.write(f'remove%testpkgc')
        state_f.close()
        self.assert_equals(self.run_command('state'), 1)
        self.assert_equals(self.run_command('state', ['--complete']), 0)
        self.assert_equals(self.run_command('state'), 0)
        self.assert_true(not Pkg.is_installed('testpkgc'))
コード例 #12
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'))
コード例 #13
0
ファイル: Installer.py プロジェクト: parsampsh/cati
    def check_dep_and_conf(self, pkg: BaseArchive):
        """
        Checks package dependencies and conflicts.

        Args:
            pkg: (BaseArchive) the package archive object

        Raises:
            DependencyError: when a dependency is not installed (dependency will put in exception message)
            ConflictError: when a conflict is installed (conflict will put in exception message)
        """

        # load package dependencies
        try:
            depends = pkg.data['depends']
        except:
            depends = []

        # load package conflicts
        try:
            conflicts = pkg.data['conflicts']
        except:
            conflicts = []

        # load package reverse cconflicts (packages has conflict to this package)
        reverse_conflicts = pkg.get_reverse_conflicts()

        for dep in depends:
            if not Pkg.check_state(dep):
                raise DependencyError(dep)

        for conflict in conflicts:
            if Pkg.check_state(conflict):
                raise ConflictError(conflict)

        # check reverse conflicts
        if reverse_conflicts:
            raise ConflictError('reverse conflict with ' + reverse_conflicts[0].data['name'] + ': ' + reverse_conflicts[0].conflict_error)
コード例 #14
0
ファイル: Calculator.py プロジェクト: parsampsh/cati
    def handle_install_conflicts(self):
        """ Adds installable packages conflicts to install list """
        new_to_remove = []
        i = 0
        while i < len(self.to_install):
            conflicts = self.to_install[i].get_conflicts()
            for conflict in conflicts:
                if Pkg.check_state(conflict):
                    # find package conflict
                    try:
                        self.to_install[i].conflict_get_next[conflict]
                    except:
                        try:
                            self.to_install[i].conflict_get_next[conflict] = 0
                        except:
                            self.to_install[i].conflict_get_next = {}
                            self.to_install[i].conflict_get_next[conflict] = 0
                    pkg = Pkg.check_state(conflict,
                                          get_true_pkg=True,
                                          get_true_pkg_next=self.to_install[i].
                                          conflict_get_next[conflict])
                    self.to_install[i].conflict_get_next[conflict] += 1
                    a = 0
                    added = False
                    if type(pkg) == list:
                        while a < len(self.to_remove):
                            if self.to_remove[a].data['name'] == pkg[0]:
                                added = True
                            a += 1
                        if not added:
                            new_to_remove.append(Pkg.load_last(pkg[0]))
            i += 1

        if new_to_remove:
            self.remove(new_to_remove)

        self.handle_install_reverse_conflicts()
コード例 #15
0
ファイル: QueryCommand.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run command """

        # join all of arguments as one argument
        full_query_string = ''
        if len(self.arguments) > 1:
            for arg in self.arguments:
                full_query_string += arg + ' '
            full_query_string = full_query_string[:len(full_query_string)-1]
        else:
            full_query_string = self.arguments[0]

        result = Pkg.check_state(full_query_string)

        if result:
            if not self.is_quiet():
                pr.p(ansi.green + 'True' + ansi.reset)
            return 0
        else:
            if not self.is_quiet():
                pr.p(ansi.red + 'False' + ansi.reset)
            return 1
コード例 #16
0
ファイル: RDependsCommand.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run command """

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

        loaded_packages = []

        for argument in self.arguments:
            pkg = Pkg.load_last(argument)
            if pkg:
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset,
                             before=ansi.red)

        if not loaded_packages:
            return 1

        # show loaded packages
        for pkg in loaded_packages:
            # load reverse depends
            rdepends = pkg.get_reverse_depends()
            if not self.is_quiet():
                pr.p(pkg.data['name'] + ':')
            if not rdepends:
                if not self.is_quiet():
                    pr.p('  This package has not any reverse dependency')
            for item in rdepends:
                if not self.is_quiet():
                    pr.p('  ' + item.data['name'] + '=' + item.data['version'])
                else:
                    pr.p(item.data['name'] + '=' + item.data['version'])
            if len(loaded_packages) > 1:
                if not self.is_quiet():
                    pr.p('========================')
コード例 #17
0
ファイル: InstallCommand.py プロジェクト: parsampsh/cati
    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
            if pkg:
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset,
                             before=ansi.red)

        # remove local packages from list
        new_loaded_packages = []
        for pkg in loaded_packages:
            try:
                file_path = pkg.data['file_path']
                new_loaded_packages.append(pkg)
            except:
                self.message('package "' + pkg.data['name'] +
                             '" is a local package',
                             is_error=True)
        loaded_packages = new_loaded_packages

        if not loaded_packages:
            return 1

        # calculate transactions
        pr.p('Calculating transactions...')
        calc = Calculator(with_recommends=self.has_option('--with-recommends'))
        i = 0
        while i < len(loaded_packages):
            loaded_packages[i].is_manual = True
            i += 1
        try:
            calc.install(list(reversed(loaded_packages)))
        except:
            pr.e(ansi.red + 'ERROR: There is some dependnecy problems.' +
                 ansi.reset)
            return 1

        # handle reinstallable packages
        i = 0
        while i < len(calc.to_install):
            if calc.to_install[i].installed():
                if calc.to_install[i].installed(
                ) == calc.to_install[i].wanted_version:
                    if not self.has_option('--reinstall'):
                        pr.p(
                            'Package ' + calc.to_install[i].data['name'] +
                            '=' + calc.to_install[i].wanted_version +
                            ' is currently installed. use --reinstall option to re-install it.'
                        )
                        if calc.to_install[i].is_manual:
                            try:
                                pr.p(
                                    'Setting it as manual installed package...'
                                )
                                manual_f = open(
                                    Env.installed_lists('/' +
                                                        pkg.data['name'] +
                                                        '/manual'), 'w')
                                manual_f.write('')
                                manual_f.close()
                            except:
                                pass
                        calc.to_install.pop(i)
            i += 1

        # check transactions exists
        if not calc.has_any_thing():
            pr.p('Nothing to do.')
            return 0

        # show transaction
        TransactionShower.show(calc)

        if not self.has_option('-y') or self.has_option('--yes'):
            pr.p('Do you want to continue? [Y/n] ', end='')
            answer = input()
            if answer == 'y' or answer == 'Y' or answer == '':
                pass
            else:
                pr.p('Abort.')
                return 1

        # start download packages
        pr.p('Downloading packages...')
        downloaed_paths = []
        for pkg in calc.to_install:
            download_path = Env.cache_dir('/archives/' + pkg.data['name'] +
                                          '-' + pkg.wanted_version + '-' +
                                          pkg.data['arch'])
            if os.path.isfile(download_path):
                file_sha256 = calc_file_sha256(download_path)
                file_md5 = calc_file_md5(download_path)
                valid_sha256 = None
                valid_md5 = None
                try:
                    valid_sha256 = pkg.data['file_sha256']
                except:
                    valid_sha256 = file_sha256
                try:
                    valid_md5 = pkg.data['file_md5']
                except:
                    valid_md5 = file_md5
                if file_md5 != valid_md5 or file_sha256 != valid_sha256:
                    # file is corrupt and should be download again
                    os.remove(download_path)
                else:
                    pr.p('Using Cache for ' + pkg.data['name'] + ':' +
                         pkg.data['version'] + ':' + pkg.data['arch'] + '...')
                    downloaed_paths.append(download_path)
                    continue
            download_cmd = DownloadCommand()
            i = 0
            res = 1
            tmp = True
            while tmp:
                if i > 5:
                    pr.e(ansi.red + 'Failed to download packages' + ansi.reset)
                    return res
                pr.p('Downloading ' + pkg.data['name'] + ':' +
                     pkg.data['version'] + ':' + pkg.data['arch'] + '...')
                res = download_cmd.handle(
                    ArgParser.parse([
                        'cati', 'download', '-q',
                        pkg.data['name'] + '=' + pkg.wanted_version,
                        '--output=' + download_path
                    ]))
                if res == 1 or res == None:
                    tmp = False
                i += 1
            downloaed_paths.append(download_path)
        pr.p('Download completed.')

        # check --download-only option
        if self.has_option('--download-only'):
            return 0

        cati_pkg_cmd_options = []
        remove_cmd_options = []
        if self.has_option('--keep-conffiles'):
            cati_pkg_cmd_options.append('--keep-conffiles')
        if self.has_option('--target'):
            cati_pkg_cmd_options.append('--target')
        if self.has_option('--without-scripts'):
            cati_pkg_cmd_options.append('--without-scripts')
            remove_cmd_options.append('--without-scripts')

        # remove packages
        if calc.to_remove:
            pr.p('Removing packages...')
            package_names = [pkg.data['name'] for pkg in calc.to_remove]
            remove_cmd = RemoveCommand()
            res = remove_cmd.handle(
                ArgParser.parse([
                    'cati', 'remove', *package_names, '-y', *remove_cmd_options
                ]))
            if res != 0 and res != None:
                pr.e(ansi.red + 'Failed to remove packages' + ansi.reset)
                return res

        # install packages
        pr.p('Installing packages...')
        pkg_cmd = PkgCommand()
        res = pkg_cmd.handle(
            ArgParser.parse([
                'cati', 'pkg', 'install', *downloaed_paths,
                *cati_pkg_cmd_options
            ]))
        if res != 0 and res != None:
            self.set_manual_installs(calc.to_install)
            pr.e(ansi.red + 'Failed to install packages' + ansi.reset)
            return res

        self.set_manual_installs(calc.to_install)

        pr.p(ansi.green + 'Done.' + ansi.reset)
コード例 #18
0
ファイル: test_install.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run test """
        repo1 = "file://" + os.getcwd(
        ) + '/repository name=test arch=all pkg=cati'
        repo2 = "file://" + os.getcwd(
        ) + '/repository name=test arch=i386 pkg=cati'

        self.assert_equals(
            self.run_command('repo',
                             ['--scan', os.getcwd() + '/repository']), 0)

        self.assert_equals(self.run_command('repo', ['--add', repo1]), 0)
        self.assert_equals(self.run_command('repo', ['--add', repo2]), 0)
        self.assert_equals(self.run_command('update'), 0)

        self.assert_equals(self.run_command('install', ['testpkg10', '-y']), 0)

        self.assert_true(Pkg.is_installed('testpkg10'))
        self.assert_true(Pkg.is_installed('testpkg11'))

        self.assert_equals(self.run_command('install', ['testpkgb', '-y']), 0)

        self.assert_true(Pkg.is_installed('testpkgb'))
        self.assert_true(Pkg.is_installed('testpkgc'))
        self.assert_true(not Pkg.is_installed_manual('testpkgc'))

        self.assert_equals(self.run_command('install', ['testpkgz', '-y']), 0)

        self.assert_true(not Pkg.is_installed('testpkgb'))
        self.assert_true(not Pkg.is_installed('testpkgc'))
        self.assert_true(Pkg.is_installed('testpkgz'))

        self.assert_equals(self.run_command('install', ['testpkgb', '-y']), 0)

        self.assert_true(Pkg.is_installed('testpkgb'))
        self.assert_true(Pkg.is_installed('testpkgc'))
        self.assert_true(not Pkg.is_installed('testpkgz'))

        self.assert_equals(
            self.run_command('remove', ['testpkgb', 'testpkgc', '-y']), 0)

        # test upgrade
        self.assert_equals(self.run_command('install', ['testpkgc=1.0', '-y']),
                           0)

        testpkgc = Pkg.load_last('testpkgc')
        self.assert_equals(testpkgc.installed(), '1.0')

        self.assert_equals(self.run_command('upgrade', ['-y']), 0)

        testpkgc = Pkg.load_last('testpkgc')
        self.assert_equals(testpkgc.installed(), '2.0')

        # test recommends
        self.refresh_env()

        self.assert_equals(
            self.run_command('repo', [
                '--add', 'file://' + os.getcwd() +
                '/repository/test-repository arch=all,i386 name=test pkg=cati'
            ]), 0)
        self.assert_equals(self.run_command('update'), 0)
        self.assert_equals(self.run_command('install', ['testpkgr', '-y']), 0)
        self.assert_true(Pkg.is_installed('testpkgr'))
        self.assert_true(Pkg.is_installed('testpkgc'))
        self.assert_true(not Pkg.is_installed('testpkg11'))

        self.refresh_env()

        self.assert_equals(
            self.run_command('repo', [
                '--add', 'file://' + os.getcwd() +
                '/repository/test-repository arch=all,i386 name=test pkg=cati'
            ]), 0)
        self.assert_equals(self.run_command('update'), 0)
        self.assert_equals(
            self.run_command('install',
                             ['testpkgr', '-y', '--with-recommends']), 0)
        self.assert_true(Pkg.is_installed('testpkgr'))
        self.assert_true(Pkg.is_installed('testpkgc'))
        self.assert_true(Pkg.is_installed('testpkg11'))
コード例 #19
0
ファイル: CheckCommand.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run command """

        # require root permission
        require_root_permission()

        result_code = 0

        packages_to_reinstall = []

        if not self.is_quiet():
            pr.p('Starting checking system health and security...')
            pr.p('===============================================')

        # check state
        state_cmd = StateCommand()
        out = state_cmd.handle(ArgParser.parse(['cati', 'state']))
        if out > 0:
            return out

        # search for conflict and dependency corruptions
        if not self.is_quiet():
            pr.p('Checking dependency and conflict corruptions...')
        dependency_problems = []
        conflict_problems = []
        installed_packages = Pkg.installed_list()['list']
        for pkg in installed_packages:
            if self.is_verbose():
                pr.p('[info] checking dependencies and conflicts for ' +
                     pkg.data['name'] + '...')
            for dp in pkg.get_depends():
                if not Pkg.check_state(dp):
                    dependency_problems.append([pkg, dp])
            for conflict in pkg.get_conflicts():
                if Pkg.check_state(conflict):
                    conflict_problems.append([pkg, conflict])

        if dependency_problems or conflict_problems:
            for depend in dependency_problems:
                pr.p(ansi.red + 'dependency problem for ' +
                     depend[0].data['name'] + ': ' + depend[1] + ansi.reset)
                packages_to_reinstall.append(depend[0])
            for conflict in conflict_problems:
                pr.p(ansi.red + 'conflict problem for ' +
                     conflict[0].data['name'] + ': ' + conflict[1] +
                     ansi.reset)
                packages_to_reinstall.append(conflict[0])
            result_code = 1
        else:
            pr.p(
                ansi.green +
                'There is not any conflict or dependnecy problem and everything is ok'
                + ansi.reset)

        # check static files
        if not self.is_quiet():
            pr.p('Checking packages static files...')
        staticfile_problems = []
        for pkg in installed_packages:
            if self.is_verbose():
                pr.p('[info] checking static files for ' + pkg.data['name'] +
                     '...')
            files = pkg.installed_static_files()
            for f in files:
                f[1] = Env.base_path(f[1])
                if os.path.isfile(f[1]):
                    wanted_hash = f[0]
                    current_hash = calc_file_sha256(f[1])
                    if wanted_hash != current_hash:
                        staticfile_problems.append([pkg, f, 'file is changed'])
                else:
                    staticfile_problems.append([pkg, f, 'file is deleted'])
        if staticfile_problems:
            for problem in staticfile_problems:
                pr.p(ansi.red + 'staticfile problem in package ' +
                     problem[0].data['name'] + ': ' + problem[1][1] + ': ' +
                     problem[2] + ansi.reset)
                packages_to_reinstall.append(problem[0])
            result_code = 1
        else:
            pr.p(ansi.green + 'all of static files are ok' + ansi.reset)

        # check repos config files health
        if not self.is_quiet():
            pr.p('Checking cati configuration files...')
        if self.is_verbose():
            pr.p('[info] checking repositories config...')
        repos = Repo.get_list()
        pr.p(ansi.red, end='')
        ReposListErrorShower.show(repos)
        pr.p(ansi.reset, end='')
        is_any_repo_error = False
        for repo in repos:
            if repo.syntax_errors:
                is_any_repo_error = True
                result_code = 1
        if not is_any_repo_error:
            pr.p(ansi.green + 'all of cati configuration files are ok' +
                 ansi.reset)

        # check database files
        if not self.is_quiet():
            pr.p('Checking cati database...')
        database_problems = []
        for f in os.listdir(Env.installed_lists()):
            if self.is_verbose():
                pr.p('[info] checking database install dir for ' + f + '...')
            if not os.path.isfile(Env.installed_lists(
                    '/' + f + '/files')) or not os.path.isfile(
                        Env.installed_lists('/' + f + '/ver')):
                database_problems.append(
                    'installed packages database: directory ' +
                    Env.installed_lists('/' + f) + ' is corrupt')
        for f in os.listdir(Env.security_blacklist()):
            if self.is_verbose():
                pr.p('[info] checking security blacklist part ' + f + '...')
            if not os.path.isfile(Env.security_blacklist('/' + f)):
                database_problems.append(
                    'security blacklist: an directory detected: ' +
                    Env.security_blacklist('/' + f))
            else:
                tmp = open(Env.security_blacklist('/' + f), 'r')
                try:
                    json.loads(tmp.read())
                except:
                    database_problems.append(
                        'security blacklist: invalid json data in ' +
                        Env.security_blacklist('/' + f))
        if database_problems:
            for problem in database_problems:
                pr.p(ansi.red + 'database: ' + problem + ansi.reset)
            result_code = 1
        else:
            pr.p(ansi.green + 'all of cati database is ok' + ansi.reset)

        if not self.is_quiet():
            if packages_to_reinstall:
                pr.p(ansi.blue + 'We suggest re-install this packages:')
                for pkg in packages_to_reinstall:
                    pr.p('- ' + pkg.data['name'])
                if not self.has_option('--autofix'):
                    pr.p(
                        'use --autofix option to re-install them or do this manually'
                    )
                    pr.p(ansi.reset, end='')
                else:
                    pr.p(ansi.reset, end='')
                    packages_names = [
                        pkg.data['name'] for pkg in packages_to_reinstall
                    ]
                    install_cmd = InstallCommand()
                    args = ['cati', 'install', '--reinstall', *packages_names]
                    cmd_str = ''
                    for arg in args:
                        cmd_str += arg + ' '
                    cmd_str = cmd_str.strip()
                    pr.p(cmd_str)
                    return install_cmd.handle(ArgParser.parse(args))

        return result_code
コード例 #20
0
ファイル: Installer.py プロジェクト: parsampsh/cati
    def install(self, pkg: BaseArchive, index_updater_events: dict, installer_events: dict, is_manual=True, run_scripts=True, target_path='', keep_conffiles=False, check_security_blacklist=True):
        """
        Install .cati package

        Args:
            pkg (BaseArchive): the package archive object
            index_updater_events (dict): events will be passed to `dotcati.ListUpdater.update_indexes()`
            installer_events (dict): The events
                - package_currently_install: gets the current installed version
                - package_new_installs: gets package archive
                - package_installed: will call after package installation
                - dep_and_conflict_error: will run when there is depends or conflict error
                - arch_error: will run when package arch is not sync with sys arch
            is_manual (bool): installed package as manual or not (default is True means manual)
            run_scripts (bool): run package install scripts or not (default is True)
            target_path (str): where is the target path for installed files (will pass to `self.copy_files()`)
            keep_conffiles (bool): stil keep config files if changed (default is True)
            check_security_blacklist (bool): check package is in security blacklist or not
        """

        self.conffiles = pkg.get_conffiles()
        self.pkg = pkg
        self.keep_conffiles = keep_conffiles
        self.uncopied_conffiles = {}

        # check package is in security blacklist
        if check_security_blacklist:
            self.check_security_blacklist(pkg)

        # check package architecture
        if not pkg.data['arch'] in SysArch.allowed_archs():
            return installer_events['arch_error'](pkg)

        # check package dependencies and conflicts
        try:
            self.check_dep_and_conf(pkg)
        except DependencyError as ex:
            return installer_events['dep_and_conflict_error'](pkg, ex)
        except ConflictError as ex:
            return installer_events['dep_and_conflict_error'](pkg, ex)

        # load old conffiles
        self.old_conffiles = []
        try:
            f = open(Env.installed_lists('/' + pkg.data['name'] + '/conffiles'), 'r')
            content = f.read()
            f.close()
            tmp = content.strip().split('\n')
            self.old_conffiles = [item.strip().split('@') for item in tmp]
        except:
            pass

        # add package data to lists
        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)

        # extract package in a temp place
        temp_dir = Temp.make_dir()
        os.rmdir(temp_dir)
        try:
            pkg.extractall(temp_dir)
        except IsADirectoryError:
            pass
        self.extracted_package_dir = temp_dir

        # install package
        if Pkg.is_installed(pkg.data['name']):
            installer_events['package_currently_installed'](pkg, Pkg.installed_version(pkg.data['name']))
        else:
            installer_events['package_new_installs'](pkg)

        if run_scripts:
            self.run_script('ins-before')

        copied_files = self.copy_files(pkg, installer_events['directory_not_empty'], target_path)

        # set install configuration
        if not os.path.isdir(Env.installed_lists('/' + pkg.data['name'])):
            os.mkdir(Env.installed_lists('/' + pkg.data['name']))
        f_ver = open(Env.installed_lists('/' + pkg.data['name'] + '/ver'), 'w')
        f_ver.write(pkg.data['version']) # write installed version
        f_ver.close()

        # write copied files list
        f_files = open(Env.installed_lists('/' + pkg.data['name'] + '/files'), 'w')
        copied_files_str = ''
        for copied_file in copied_files:
            copied_files_str += copied_file + '\n'
        f_files.write(copied_files_str.strip()) # write copied files
        f_files.close()

        # write conffiles list
        f_conffiles = open(Env.installed_lists('/' + pkg.data['name'] + '/conffiles'), 'w')
        copied_conffiles_str = ''
        for copied_conffile in copied_files:
            if copied_conffile.split(':')[0] == 'cf':
                try:
                    conffile_hash = self.uncopied_conffiles[copied_conffile.split(':', 1)[-1]]
                except:
                    conffile_hash = calc_file_sha256(Env.base_path(copied_conffile.split(':', 1)[-1]))
                copied_conffiles_str += conffile_hash + '@' + copied_conffile.split(':', 1)[-1] + '\n'
        f_conffiles.write(copied_conffiles_str.strip()) # write copied conffiles
        f_conffiles.close()

        # copy `any` script
        if os.path.isfile(self.extracted_package_dir + '/scripts/any'):
            os.system('cp "' + self.extracted_package_dir + '/scripts/any' + '" "' + Env.any_scripts('/' + pkg.data['name']) + '"')

        # save static files list
        static_files_list = pkg.get_static_files()
        f_static_files = open(Env.installed_lists('/' + pkg.data['name'] + '/staticfiles'), 'w')
        static_files_str = ''
        for copied_file in copied_files:
            copied_file_path = copied_file.split(':', 1)[1]
            if copied_file_path in static_files_list:
                if os.path.isfile(Env.base_path('/' + copied_file_path)):
                    # calculate file sha256 sum
                    copied_file_sha256 = calc_file_sha256(Env.base_path('/' + copied_file_path))
                    # add file to list
                    static_files_str += copied_file_sha256 + '@' + copied_file_path + '\n'
        f_static_files.write(static_files_str.strip()) # write copied files
        f_static_files.close()

        f_installed_at = open(Env.installed_lists('/' + pkg.data['name'] + '/installed_at'), 'w')
        f_installed_at.write(str(time.time())) # write time (installed at)
        f_installed_at.close()

        if is_manual:
            f_manual = open(Env.installed_lists('/' + pkg.data['name'] + '/manual'), 'w')
            f_manual.write('')
            f_manual.close()

        if run_scripts:
            self.run_script('ins-after')

        # copy remove scripts
        if os.path.isfile(self.extracted_package_dir + '/scripts/rm-before'):
            os.system(
                'cp "' + self.extracted_package_dir + '/scripts/rm-before' + '" "' + Env.installed_lists('/' + pkg.data['name'] + '/rm-before') + '"'
            )
        if os.path.isfile(self.extracted_package_dir + '/scripts/rm-after'):
            os.system(
                'cp "' + self.extracted_package_dir + '/scripts/rm-after' + '" "' + Env.installed_lists('/' + pkg.data['name'] + '/rm-after') + '"'
            )

        # pop package from state
        BaseTransaction.pop_state()

        # call package installed event
        installer_events['package_installed'](pkg)
コード例 #21
0
ファイル: FilesCommand.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run command """

        if self.has_option('--installed'):
            if not self.is_quiet():
                pr.p('Loading files list...')
                pr.p('=====================')
            all_of_installed_files_list = Pkg.get_all_installed_files_list()
            for item in all_of_installed_files_list:
                if self.is_quiet():
                    pr.p(item[2])
                else:
                    message = ''
                    if item[1] == 'd':
                        message = ' (directory)'
                    elif item[1] == 'cf':
                        message = ' (config file)'
                    elif item[1] == 'cd':
                        message = ' (config directory)'
                    pr.p(item[0] + ': ' + item[2] + message)
            return 0

        if not self.arguments:
            self.message('argument package names is required', True)
            return 1

        if not self.is_quiet():
            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
            if pkg:
                loaded_packages.append(pkg)
            else:
                self.message('unknow package "' + argument + '"' + ansi.reset,
                             before=ansi.red)

        if not loaded_packages:
            return 1

        # show files list of loaded packages
        for pkg in loaded_packages:
            try:
                files_list = pkg.data['files']
            except:
                files_list = []
            if not self.is_quiet():
                pr.p(pkg.data['name'] + ':')
                if not files_list:
                    pr.p(ansi.yellow + '  This package is empty' + ansi.reset)
                for item in files_list:
                    pr.p('  ' + item)
            else:
                for item in files_list:
                    pr.p(item)
            if len(loaded_packages) > 1:
                if not self.is_quiet():
                    pr.p('========================')
コード例 #22
0
ファイル: Calculator.py プロジェクト: parsampsh/cati
    def handle_install_depends(self):
        """ Adds installable packages depends to install list """
        new_to_install = []
        i = 0
        while i < len(self.to_install):
            depends = self.to_install[i].get_depends()
            if self.with_recommends:
                depends = [*depends, *self.to_install[i].get_recommends()]
            for depend in depends:
                if not Pkg.check_state(depend) and depend.strip()[0] != '@':
                    # find package depend
                    try:
                        self.to_install[i].depend_get_next[depend]
                    except:
                        try:
                            self.to_install[i].depend_get_next[depend] = 0
                        except:
                            self.to_install[i].depend_get_next = {}
                            self.to_install[i].depend_get_next[depend] = 0
                    pkg = Pkg.check_state(
                        depend,
                        get_false_pkg=True,
                        get_false_pkg_next=self.to_install[i].
                        depend_get_next[depend])
                    self.to_install[i].depend_get_next[depend] += 1
                    if len(pkg) == 1:
                        a = 0
                        added = False
                        while a < len(self.to_install):
                            if self.to_install[a].data['name'] == pkg[0]:
                                added = True
                            a += 1
                        if not added:
                            new_to_install.append(Pkg.load_last(pkg[0]))
                    elif len(pkg) == 3:
                        a = 0
                        added = False
                        while a < len(self.to_install):
                            if self.to_install[a].data['name'] == pkg[0]:
                                wanted_version = pkg[2]
                                installed_version = self.to_install[
                                    a].wanted_version
                                if pkg[1] == '=':
                                    if Pkg.compare_version(
                                            installed_version,
                                            wanted_version) == 0:
                                        added = True
                                elif pkg[1] == '>=':
                                    if Pkg.compare_version(
                                            installed_version,
                                            wanted_version) >= 0:
                                        added = True
                                elif pkg[1] == '<=':
                                    if Pkg.compare_version(
                                            installed_version,
                                            wanted_version) <= 0:
                                        added = True
                                elif pkg[1] == '>':
                                    if Pkg.compare_version(
                                            installed_version,
                                            wanted_version) == 1:
                                        added = True
                                elif pkg[1] == '<':
                                    if Pkg.compare_version(
                                            installed_version,
                                            wanted_version) == -1:
                                        added = True
                            a += 1
                        if not added:
                            pkg_obj = None
                            if pkg[1] == '=':
                                pkg_obj = Pkg.load_version(pkg[0], pkg[2])
                            elif pkg[1] == '>=' or pkg[1] == '>':
                                pkg_obj = Pkg.load_last(pkg[0])
                            elif pkg[1] == '<=':
                                pkg_obj = Pkg.load_version(pkg[0], pkg[2])
                            elif pkg[1] == '<':
                                pkg_obj = Pkg.load_last(pkg[0])
                                versions = pkg_obj.get_versions_list()
                                x = 0
                                while x < len(versions):
                                    if Pkg.compare_version(
                                            versions[x][0], pkg[0]) >= 0:
                                        versions.pop(x)
                                    x += 1
                                versions = [v[0] for v in versions]
                                wanted_ver = pkg.get_last_version(versions)
                                pkg_obj = Pkg.load_version(pkg[0], wanted_ver)
                            new_to_install.append(pkg_obj)
            i += 1

        if new_to_install:
            self.install(new_to_install)

        self.handle_install_reverse_depends()
コード例 #23
0
    def run(self):
        """ Run test """
        self.assert_equals(self.run_command('pkg', [
            'install',
            'repository/test-repository/testpkg10.cati'
        ]), 1)

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

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

        self.assert_true(Pkg.is_installed('testpkg10'))
        self.assert_true(Pkg.is_installed('testpkg11'))

        self.assert_equals(self.run_command('remove', [
            'testpkg10',
            '-y'
        ]), 0)

        self.assert_true(not Pkg.is_installed('testpkg10'))
        self.assert_true(Pkg.is_installed('testpkg11'))

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

        self.assert_true(Pkg.is_installed('testpkg10'))
        self.assert_true(Pkg.is_installed('testpkg11'))

        self.assert_equals(self.run_command('remove', [
            'testpkg11',
            '-y'
        ]), 0)

        self.assert_true(not Pkg.is_installed('testpkg10'))
        self.assert_true(not Pkg.is_installed('testpkg11'))

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

        self.assert_true(Pkg.is_installed('essential-package'))

        self.assert_equals(self.run_command('remove', [
            'essential-package',
            '-y'
        ]), 1)

        self.assert_true(Pkg.is_installed('essential-package'))

        self.assert_equals(self.run_command('remove', [
            'essential-package',
            '-y',
            '--force'
        ]), 0)

        self.assert_true(not Pkg.is_installed('essential-package'))
コード例 #24
0
ファイル: Installer.py プロジェクト: parsampsh/cati
    def copy_files(self, pkg: BaseArchive, directory_not_empty_event, target_path='') -> list:
        """
        Copy package files on system

        Args:
            pkg (BaseArchive): the package archive object
            directory_not_empty_event (callable): the function will be run when we want to delete old direcotry
                                      of package and that is not empty.
            target_path (str): target path prefix of copied files location. default is `/` means
                               copies files on the root directory. you can change it.

        Returns:
            list[str]: list of copied files
        """
        # load package old files list
        old_files = []
        if os.path.isfile(Env.installed_lists('/' + pkg.data['name'] + '/files')):
            try:
                f = open(Env.installed_lists('/' + pkg.data['name'] + '/files'), 'r')
                for line in f.read().strip().split('\n'):
                    if line != '':
                        old_files.append(line.strip())
            except:
                pass
        old_files = list(reversed(old_files))

        # load unremoved conffiles list
        unremoved_conffiles_f = open(Env.unremoved_conffiles(), 'r')
        unremoved_conffiles = unremoved_conffiles_f.read().strip().split('\n')
        unremoved_conffiles_f.close()

        temp_dir = self.extracted_package_dir

        # load files list from `files` directory of package
        self.loaded_files = []
        self.load_files(temp_dir + '/files', temp_dir + '/files')
        self.loaded_files = [[target_path + f[0], f[1]] for f in self.loaded_files]

        # check file conflicts
        all_installed_files = Pkg.get_all_installed_files_list()
        for lf in self.loaded_files:
            if not os.path.isdir(lf[1]):
                for insf in all_installed_files:
                    if insf[0].split(':', 1)[0] != pkg.data['name']:
                        if lf[0] == insf[2]:
                            insf_pkg = Pkg.load_last(insf[0])
                            if insf_pkg:
                                insf[0] = insf[0] + ':' + insf_pkg.installed()
                            # check package is in `replaces` list
                            do_raise_error = True
                            replaces_list = pkg.get_replaces()
                            for rep in replaces_list:
                                if Pkg.check_state(rep):
                                    tmp_parts = rep.split(' ')
                                    tmp_parts = tmp_parts[0].split('>')
                                    tmp_parts = tmp_parts[0].split('<')
                                    tmp_parts = tmp_parts[0].split('=')
                                    tmp_parts = tmp_parts[0]
                                    if tmp_parts == insf[0].split(':', 1)[0]:
                                        do_raise_error = False
                            if do_raise_error:
                                raise FileConflictError(
                                    'package ' + pkg.data['name'] + ':' + pkg.data['version'] + ' and ' + insf[0] + ' both has file "' + lf[0] + '"'
                                )

        # copy loaded files
        self.copied_files = []
        for f in self.loaded_files:
            if os.path.exists(Env.base_path(f[0])):
                if os.path.isfile(Env.base_path(f[0])):
                    if ('f:' + f[0]) in old_files or ('cf:' + f[0]) in old_files:
                        self.copy_once_file(f)
                        try:
                            old_files.pop(old_files.index(('f:' + f[0])))
                        except:
                            pass
                    else:
                        if f[0] in unremoved_conffiles:
                            self.copy_once_file(f)
                            unremoved_conffiles.pop(unremoved_conffiles.index(f[0]))
                        else:
                            self.copy_once_file(f)
                else:
                    if ('d:' + f[0]) in old_files or ('cd:' + f[0]) in old_files:
                        if ('cd:' + f[0]) in old_files:
                            self.copied_files.append('cd:' + f[0])
                            old_files.pop(old_files.index(('cd:' + f[0])))
                        else:
                            self.copied_files.append('d:' + f[0])
                            old_files.pop(old_files.index(('d:' + f[0])))
                    else:
                        if f[0] in unremoved_conffiles:
                            self.copied_files.append('d:' + f[0])
                            unremoved_conffiles.pop(unremoved_conffiles.index(f[0]))
            else:
                self.copy_once_file(f)

        # delete not wanted old files
        for item in old_files:
            parts = item.strip().split(':', 1)
            if parts[0] == 'cf' or parts[0] == 'cd':
                pass
            else:
                if os.path.isfile(parts[1]):
                    os.remove(parts[1])
                else:
                    try:
                        os.rmdir(parts[1])
                    except:
                        # directory is not emptyr
                        directory_not_empty_event(pkg, parts[1])

        # write new unremoved conffiles list
        unremoved_conffiles_f = open(Env.unremoved_conffiles(), 'w')
        new_content = ''
        for item in unremoved_conffiles:
            new_content += item + '\n'
        unremoved_conffiles_f.write(new_content)
        unremoved_conffiles_f.close()

        return self.copied_files
コード例 #25
0
ファイル: PackageShower.py プロジェクト: parsampsh/cati
def show(data: dict):
    """
    shows package information from data dictonary.
    
    Args:
        data: (dict) package data dictonary
    """
    output = ''
    output += 'Name: ' + ansi.green + data['name'] + ansi.reset + '\n'
    output += 'Version: ' + ansi.blue + data['version'] + ansi.reset + '\n'
    output += 'Arch: ' + ansi.yellow + data['arch'] + ansi.reset + '\n'
    try:
        author = data['author']
        output += 'Author: ' + ansi.header + author + ansi.reset + '\n'
    except:
        pass
    try:
        maintainer = data['maintainer']
        output += 'Maintainer: ' + ansi.cyan + maintainer + ansi.reset + '\n'
    except:
        pass
    try:
        changed_by = data['changed-by']
        output += 'Changed-By: ' + changed_by + '\n'
    except:
        pass
    try:
        uploaders = data['uploaders']
    except:
        uploaders = []
    if uploaders:
        output += 'Uploaders: '
        for uploader in uploaders:
            output += uploader + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        channel = data['channel']
        output += 'Channel: ' + ansi.red + channel + ansi.reset + '\n'
    except:
        pass
    try:
        homepage = data['homepage']
        output += 'Homepage: ' + ansi.blue + homepage + ansi.reset + '\n'
    except:
        pass
    try:
        category = data['category']
        if category:
            output += 'Categories: '
            i = 0
            while i < len(category):
                output += ansi.bold + category[i] + ansi.reset
                if i < len(category) - 1:
                    output += ', '
                i += 1
            output += '\n'
    except:
        pass
    try:
        description = data['description']
        output += 'Description: ' + description + '\n'
    except:
        pass
    try:
        changes = data['changes']
        output += 'Changes: ' + description + '\n'
    except:
        pass
    try:
        date = data['date']
        output += 'Last-Update-Date: ' + date + '\n'
    except:
        pass
    try:
        urgency = data['urgency']
        output += 'Update-Level: ' + urgency + '\n'
    except:
        pass
    try:
        essential = data['essential']
        if essential:
            essential = 'Yes'
        else:
            essential = 'No'
        output += 'Essential: ' + essential + '\n'
    except:
        pass
    try:
        file_size = Pkg.get_download_size_str(data['file_size'])
        output += 'Download-Size: ' + str(file_size) + '\n'
    except:
        pass
    try:
        installed_size = Pkg.get_download_size_str(data['installed-size'])
        output += 'Installed-Size: ' + str(installed_size) + '\n'
    except:
        pass
    try:
        repo = data['repo']
        output += 'Repository: ' + repo + '\n'
    except:
        pass
    try:
        depends = data['depends']
    except:
        depends = []
    if depends:
        output += 'Depends: '
        for dep in depends:
            output += ansi.bold + dep + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        recommends = data['recommends']
    except:
        recommends = []
    if recommends:
        output += 'Recommends: '
        for rec in recommends:
            output += ansi.bold + rec + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        conflicts = data['conflicts']
    except:
        conflicts = []
    if conflicts:
        output += 'Conflicts: '
        for conflict in conflicts:
            output += ansi.bold + conflict + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        suggests = data['suggests']
    except:
        suggests = []
    if suggests:
        output += 'Suggests: '
        for suggest in suggests:
            output += ansi.bold + suggest + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        enhances = data['enhances']
    except:
        enhances = []
    if enhances:
        output += 'Enhances: '
        for enhance in enhances:
            output += ansi.bold + enhance + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    try:
        provides = data['provides']
    except:
        provides = []
    if provides:
        output += 'Provides: '
        for provide in provides:
            output += ansi.bold + provide + ansi.reset + ', '
        output = output[:len(output) - 2]
        output += '\n'
    if Pkg.is_installed(data['name']):
        installed_version = Pkg.installed_version(data['name'])
        if Pkg.is_installed_manual(data['name']):
            output += 'Installed-Manual: ' + installed_version + '\n'
        else:
            output += 'Installed: ' + installed_version + '\n'

    # show user defined fields
    for k in data:
        if k[0] == 'x' or k[0] == 'X':
            # that fields start with `x` character are user defined fields
            output += '\n' + k + ': ' + data[k]

    if output[-1] == '\n':
        output = output[:len(output) - 1]
    pr.p(output.strip())
コード例 #26
0
    def run(self):
        """ Run command """

        require_root_permission()

        # check transactions state before run new transactions
        pr.p('Checking transactions state...')
        state_list = BaseTransaction.state_list(
        )  # get list of undoned transactions
        if state_list:
            # the list is not empty
            StateContentShower.show(state_list)
            return 1

        pr.p('Loading packages list...')
        pr.p('==============================')
        # load list of packages
        packages = []
        for arg in self.arguments:
            pkg = Pkg.load_last(arg)
            if pkg == False:
                self.message('unknow package "' + arg + '"' + ansi.reset,
                             before=ansi.red)
            else:
                if pkg.installed():
                    packages.append(pkg)
                else:
                    self.message('package "' + pkg.data['name'] +
                                 '" is not installed' + ansi.reset,
                                 before=ansi.red)

        # start removing loaded packages
        calc = Calculator()
        calc.remove(packages)

        # show transactions
        TransactionShower.show(calc)

        essential_packages = []
        for pkg in calc.to_remove:
            try:
                if pkg.data['essential']:
                    essential_packages.append(pkg)
            except:
                pass

        if not self.has_option('--force') and not self.has_option('-f'):
            for pkg in essential_packages:
                pr.p(
                    ansi.red + 'Package "' + pkg.data['name'] +
                    '" is a essential package and cannot be remove. use --force|-f option to force remove them'
                    + ansi.reset)
            if essential_packages:
                return 1

        if not calc.has_any_thing():
            return

        # check user confirmation
        if not self.has_option('-y') and not self.has_option('--yes'):
            pr.p('Do you want to continue? [Y/n] ', end='')
            answer = input()
            if not (answer == 'y' or answer == 'Y' or answer == ''):
                pr.p(ansi.yellow + 'Abort.' + ansi.reset)
                pr.exit(1)

        # add packages to state
        BaseTransaction.add_to_state(calc)

        packages_to_remove_names_and_versions = [
            pkg.data['name'] + '@' + pkg.data['version']
            for pkg in calc.to_remove
        ]

        # run transactions
        for pkg in calc.to_remove:
            Remove.run(pkg, {
                'removing_package': self.removing_package_event,
                'package_remove_finished': self.package_remove_finished_event,
                'dir_is_not_empty': self.dir_is_not_empty_event,
            },
                       self.has_option('--conffiles'),
                       run_scripts=(not self.has_option('--without-scripts')))
            BaseTransaction.pop_state()

        BaseTransaction.run_any_scripts(
            ['remove', packages_to_remove_names_and_versions],
            events={
                'start_run_script': self.start_run_any_script_event,
            })

        BaseTransaction.finish_all_state()
コード例 #27
0
ファイル: test_forget_command.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run test """
        self.assert_equals(self.run_command('pkg', [
            'install',
            'repository/test-repository/testpkgc-1.0.cati'
        ]), 0)

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

        self.assert_equals(self.run_command('forget', [
            'testpkgc'
        ]), 1)

        self.assert_equals(self.run_command('remove', [
            'testpkgc',
            '-y'
        ]), 0)

        self.assert_equals(self.run_command('forget', [
            'testpkgc'
        ]), 0)

        self.assert_true(not Pkg.load_last('testpkgc'))

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

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

        self.assert_equals(self.run_command('forget', [
            'testpkgc=1.0'
        ]), 0)

        self.assert_equals(self.run_command('forget', [
            'testpkgc=2.0'
        ]), 1)

        self.refresh_env()

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

        self.assert_equals(self.run_command('pkg', [
            'install',
            'repository/test-repository/testpkgc-2.0-alpha.cati'
        ]), 0)

        self.assert_equals(self.run_command('forget', [
            'testpkgc=2.0'
        ]), 0)

        self.assert_true(not os.path.isfile(self.env() + '/var/lib/cati/lists/testpkgc/2.0-all'))
        self.assert_true(os.path.isfile(self.env() + '/var/lib/cati/lists/testpkgc/2.0-alpha-all'))
コード例 #28
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,
        })
コード例 #29
0
ファイル: ListCommand.py プロジェクト: parsampsh/cati
    def run(self):
        """ Run command """

        if not self.has_option('-q') and not self.has_option('--quiet'):
            pr.p('Loading packages list...')
            pr.p('========================')
        # load list of packages
        if self.has_option('--installed'):
            # just list installed packages
            packages = Pkg.installed_list()
        elif self.has_option('--installed-manual'):
            packages = Pkg.installed_list()
            packages_list = [
                tmp_pkg for tmp_pkg in packages['list']
                if Pkg.is_installed_manual(tmp_pkg.data['name'])
            ]
            packages['list'] = packages_list
        else:
            packages = Pkg.all_list()

        for error in packages['errors']:
            self.message(error + ansi.reset, True, before=ansi.red)

        # load filter options
        wanted_authors = []
        if self.has_option('--author'):
            wanted_authors = self.option_value('--author').strip().split('|')
            wanted_authors = [author.strip() for author in wanted_authors]
        wanted_maintainers = []
        if self.has_option('--maintainer'):
            wanted_maintainers = self.option_value(
                '--maintainer').strip().split('|')
            wanted_maintainers = [
                maintainer.strip() for maintainer in wanted_maintainers
            ]
        wanted_categories = []
        if self.has_option('--category'):
            wanted_categories = self.option_value('--category').strip().split(
                '|')
            wanted_categories = [
                category.strip() for category in wanted_categories
            ]
        search_query = self.option_value('--search')
        if search_query:
            search_query_words = search_query.strip().split(' ')
            search_query_words = [word.strip() for word in search_query_words]
        else:
            search_query_words = []

        for package in packages['list']:
            # check filters
            if wanted_authors:
                try:
                    if not package.data['author'].strip() in wanted_authors:
                        continue
                except:
                    continue
            if wanted_maintainers:
                try:
                    if not package.data['maintainer'].strip(
                    ) in wanted_maintainers:
                        continue
                except:
                    continue
            if wanted_categories:
                try:
                    if not package.data['category'].strip(
                    ) in wanted_categories:
                        continue
                except:
                    continue
            if search_query:
                is_math_with_query = False
                for word in search_query_words:
                    if word in package.data['name']:
                        is_math_with_query = True
                try:
                    if search_query in package.data['description']:
                        is_math_with_query = True
                except:
                    pass
                if not is_math_with_query:
                    continue

            if self.has_option('--upgradable'):
                if package.installed():
                    if Pkg.compare_version(package.data['version'],
                                           package.installed()) != 1:
                        continue
                else:
                    continue
            # show item
            self.show_once(package)
コード例 #30
0
    def run(self):
        """ Run test """
        self.assert_equals(self.run_command('autoremove', []), 0)

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

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

        self.assert_true(Pkg.is_installed('testpkg11'))
        self.assert_true(Pkg.is_installed('testpkg10'))

        self.assert_equals(self.run_command('autoremove', ['-y']), 0)

        self.assert_true(Pkg.is_installed('testpkg11'))
        self.assert_true(Pkg.is_installed('testpkg10'))

        self.assert_equals(self.run_command('remove', [
            '-y',
            'testpkg10',
        ]), 0)

        self.assert_true(Pkg.is_installed('testpkg11'))
        self.assert_true(not Pkg.is_installed('testpkg10'))

        self.assert_equals(self.run_command('autoremove', ['-y']), 0)

        self.assert_true(not Pkg.is_installed('testpkg11'))
        self.assert_true(not Pkg.is_installed('testpkg10'))

        self.refresh_env()

        self.assert_equals(
            self.run_command('pkg', [
                'install',
                'repository/test-repository/testpkg11.cati',
                'repository/test-repository/testpkg10.cati',
                '--auto',
            ]), 0)

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

        self.assert_true(Pkg.is_installed('testpkg11'))
        self.assert_true(Pkg.is_installed('testpkg10'))
        self.assert_true(Pkg.is_installed('testpkg9'))

        self.assert_equals(self.run_command('remove', [
            '-y',
            'testpkg9',
        ]), 0)

        self.assert_true(Pkg.is_installed('testpkg11'))
        self.assert_true(Pkg.is_installed('testpkg10'))
        self.assert_true(not Pkg.is_installed('testpkg9'))

        self.assert_equals(self.run_command('autoremove', ['-y']), 0)

        self.assert_true(not Pkg.is_installed('testpkg11'))
        self.assert_true(not Pkg.is_installed('testpkg10'))
        self.assert_true(not Pkg.is_installed('testpkg9'))