1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/*
* Copyright (C) Serenity Cybersecurity, LLC <license@futurecrew.ru>
* Author: Gleb Popov <arrowd@FreeBSD.org>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <pkg.h>
#include "PackageView.hpp"
class Jobs {
public:
class iterator {
friend class Jobs;
public:
bool operator==(const iterator& other) const {
return pkgIter == other.pkgIter;
}
bool operator!=(const iterator& other) const {
return pkgIter != other.pkgIter;
}
iterator& operator++() {
if (!pkg_jobs_iter(jobsHandle, &pkgIter, &newPkg, &oldPkg, &type))
pkgIter = nullptr;
return *this;
}
PackageView oldPkgView() const { return oldPkg; }
PackageView newPkgView() const { return newPkg; }
pkg* oldPkgHandle() const { return oldPkg; }
pkg* newPkgHandle() const { return newPkg; }
int itemType() const { return type; }
private:
pkg_jobs* jobsHandle;
void* pkgIter = nullptr;
pkg* oldPkg;
pkg* newPkg;
int type;
};
Jobs(pkg_jobs_t jobsType, pkgdb* dbHandle, const char* _context = "")
: context(_context), jobsHandle(nullptr), jobsFlags(PKG_FLAG_NONE) {
if (pkg_jobs_new(&jobsHandle, jobsType, dbHandle) != EPKG_OK)
g_error("%s: pkg_jobs_new failed", context);
}
Jobs& operator<<(pkg_flags flag) {
jobsFlags = static_cast<pkg_flags> (jobsFlags | flag);
return *this;
}
void setFlags(pkg_flags flags) { jobsFlags = flags; }
void setDestination(const std::string& dest) const { setDestination(dest.c_str()); }
void setDestination(const char* dest) const {
if (pkg_jobs_set_destdir(jobsHandle, dest) != EPKG_OK)
g_error("%s: pkg_jobs_add failed", context);
}
void add(match_t matchType, char **argv, int argc) {
if (pkg_jobs_add(jobsHandle, matchType, argv, argc) == EPKG_FATAL)
g_error("%s: pkg_jobs_add failed", context);
}
void add(match_t matchType, std::vector<char*> argv) {
if (pkg_jobs_add(jobsHandle, matchType, argv.data(), argv.size()) == EPKG_FATAL)
g_error("%s: pkg_jobs_add failed", context);
}
int solve() {
pkg_jobs_set_flags(jobsHandle, jobsFlags);
if (pkg_jobs_solve(jobsHandle) != EPKG_OK)
g_warning("%s: pkg_jobs_solve failed", context);
jobsCount = pkg_jobs_count(jobsHandle);
return jobsCount;
}
int count() const { return jobsCount; }
bool hasLockedPackages() const { return pkg_jobs_has_lockedpkgs(jobsHandle); }
bool apply() {
int retcode;
do {
retcode = pkg_jobs_apply(jobsHandle);
if (retcode == EPKG_CONFLICT) {
g_warning("Conflicts with the existing packages "
"have been found. One more solver "
"iteration is needed to resolve them.");
}
else if (retcode == EPKG_CANCEL) {
g_message ("%s: pkg_jobs_apply cancelled", context);
return true;
}
else if (retcode != EPKG_OK) {
// libpkg doesn't yet return sensible error codes from pkg_jobs_apply
g_warning ("%s: pkg_jobs_apply failed", context);
return false;
}
} while (retcode != EPKG_OK);
return true;
}
iterator begin() {
void *pkgIter = nullptr;
pkg *newPkg = nullptr, *oldPkg = nullptr;
int type;
if (pkg_jobs_iter(jobsHandle, &pkgIter, &newPkg, &oldPkg, &type)) {
// TODO: I find it stupid that an iterator stores so much information
iterator ret;
ret.jobsHandle = jobsHandle;
ret.pkgIter = pkgIter;
ret.oldPkg = oldPkg;
ret.newPkg = newPkg;
ret.type = type;
return ret;
}
else return end();
}
iterator end() { return iterator(); }
~Jobs() {
pkg_jobs_free(jobsHandle);
}
private:
const char* context;
pkg_jobs* jobsHandle;
pkg_flags jobsFlags;
int jobsCount;
};
|