clean-reqs: add autoremove feature

This commit is contained in:
Oliver Kurth 2021-10-26 22:33:19 +00:00
parent 3a8b04d34f
commit 09a630ae88
14 changed files with 370 additions and 38 deletions

View File

@ -1580,12 +1580,6 @@ TDNFResolve(
queue_init(&queueGoal);
}
if(nAlterType == ALTER_AUTOERASE)
{
dwError = ERROR_TDNF_AUTOERASE_UNSUPPORTED;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFValidateCmdArgs(pTdnf);
BAIL_ON_TDNF_ERROR(dwError);

View File

@ -127,6 +127,9 @@ typedef enum
#define TDNF_REPO_METALINK_FILE_NAME "metalink"
#define TDNF_REPO_BASEURL_FILE_NAME "baseurl"
#define TDNF_AUTOINSTALLED_FILE "autoinstalled"
#define TDNF_DEFAULT_DATA_LOCATION "/var/lib/tdnf"
// repo defaults
#define TDNF_DEFAULT_REPO_LOCATION "/etc/yum.repos.d"
#define TDNF_DEFAULT_CACHE_LOCATION "/var/cache/tdnf"

View File

@ -316,6 +316,7 @@ TDNFGoal(
int nProblems = 0;
char** ppszExcludes = NULL;
uint32_t dwExcludeCount = 0;
char **ppszAutoInstalled = NULL;
if(!pTdnf || !ppInfo || !pQueuePkgList)
{
@ -357,8 +358,9 @@ TDNFGoal(
{
nFlags = nFlags | SOLVER_FORCEBEST;
}
if (pTdnf->pConf->nCleanRequirementsOnRemove)
if ((pTdnf->pConf->nCleanRequirementsOnRemove &&
!pTdnf->pArgs->nNoAutoRemove) ||
nAlterType == ALTER_AUTOERASE)
{
nFlags = nFlags | SOLVER_CLEANDEPS;
}
@ -394,6 +396,12 @@ TDNFGoal(
nAlterType == ALTER_ERASE ||
nAlterType == ALTER_AUTOERASE)
{
dwError = TDNFReadAutoInstalled(pTdnf, &ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
dwError = SolvAddUserInstalledToJobs(&queueJobs, pTdnf->pSack->pPool, ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
solver_set_flag(pSolv, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
}
solver_set_flag(pSolv, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
@ -412,7 +420,7 @@ TDNFGoal(
if (nAlterType == ALTER_UPGRADE && dwExcludeCount != 0 && ppszExcludes)
{
/* if we had packages to exclude, then we'd have diabled ones too */
/* if we had packages to exclude, then we'd have disabled ones too */
dwSkipProblem |= SKIPPROBLEM_DISABLED;
}
@ -434,16 +442,22 @@ TDNFGoal(
}
dwError = TDNFGoalGetAllResultsIgnoreNoData(
nAlterType,
pTrans,
pSolv,
&pInfoTemp,
pTdnf);
BAIL_ON_TDNF_ERROR(dwError);
if (nAlterType == ALTER_INSTALL)
{
dwError = TDNFAddUserInstall(pTdnf, pQueuePkgList, pInfoTemp);
BAIL_ON_TDNF_ERROR(dwError);
}
*ppInfo = pInfoTemp;
cleanup:
TDNF_SAFE_FREE_STRINGARRAY(ppszAutoInstalled);
TDNF_SAFE_FREE_STRINGARRAY(ppszExcludes);
queue_free(&queueJobs);
if(pTrans)
@ -465,6 +479,211 @@ error:
goto cleanup;
}
uint32_t
TDNFAddUserInstall(
PTDNF pTdnf,
Queue* pQueueGoal,
PTDNF_SOLVED_PKG_INFO ppInfo
)
{
uint32_t dwError = 0;
int i;
char **ppszPkgsUserInstall = NULL;
if (!pTdnf || !pQueueGoal || !ppInfo)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFAllocateMemory(pQueueGoal->count + 1,
sizeof(char **),
(void **)&ppszPkgsUserInstall);
BAIL_ON_TDNF_ERROR(dwError);
for (i = 0; i < pQueueGoal->count; i++)
{
dwError = SolvGetPkgNameFromId(
pTdnf->pSack,
pQueueGoal->elements[i],
&ppszPkgsUserInstall[i]);
BAIL_ON_TDNF_ERROR(dwError);
}
ppInfo->ppszPkgsUserInstall = ppszPkgsUserInstall;
cleanup:
return dwError;
error:
TDNF_SAFE_FREE_MEMORY(ppszPkgsUserInstall);
goto cleanup;
}
uint32_t
TDNFMarkAutoInstalledSinglePkg(
PTDNF pTdnf,
const char *pszPkgName
)
{
uint32_t dwError = 0;
char **ppszAutoInstalled = NULL;
char *pszAutoFile = NULL;
int i;
FILE *fp = NULL;
if (!pTdnf || !pszPkgName)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadAutoInstalled(pTdnf, &ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFJoinPath(&pszAutoFile,
pTdnf->pArgs->pszInstallRoot,
TDNF_DEFAULT_DATA_LOCATION,
TDNF_AUTOINSTALLED_FILE,
NULL);
BAIL_ON_TDNF_ERROR(dwError);
fp = fopen(pszAutoFile, "w");
if(!fp)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
for (i = 0; ppszAutoInstalled[i]; i++)
{
if (strcmp(ppszAutoInstalled[i], pszPkgName) == 0)
{
pr_info("marking %s as user installed\n", pszPkgName);
continue;
}
fprintf(fp, "%s\n", ppszAutoInstalled[i]);
}
fclose(fp);
cleanup:
TDNF_SAFE_FREE_MEMORY(pszAutoFile);
TDNF_SAFE_FREE_STRINGARRAY(ppszAutoInstalled);
return dwError;
error:
if (fp)
{
fclose(fp);
}
goto cleanup;
}
uint32_t
TDNFMarkAutoInstalled(
PTDNF pTdnf,
PTDNF_SOLVED_PKG_INFO ppInfo
)
{
uint32_t dwError = 0;
PTDNF_PKG_INFO pPkgInfo = NULL;
char **ppszAutoInstalled = NULL;
int i, j;
int nCount = 0;
int nCountOld = 0;
FILE *fp = NULL;
char *pszAutoFile = NULL;
char *pszDataDir = NULL;
if (!pTdnf || !ppInfo)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFReadAutoInstalled(pTdnf, &ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
if (ppszAutoInstalled != NULL)
{
dwError = TDNFStringArrayCount(ppszAutoInstalled, &nCount);
BAIL_ON_TDNF_ERROR(dwError);
}
nCountOld = nCount;
for (pPkgInfo = ppInfo->pPkgsToInstall; pPkgInfo; pPkgInfo = pPkgInfo->pNext)
{
nCount++;
}
dwError = TDNFReAllocateMemory((nCount+1) * sizeof(char **), (void **)&ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
ppszAutoInstalled[nCount] = NULL;
for (pPkgInfo = ppInfo->pPkgsToInstall; pPkgInfo; pPkgInfo = pPkgInfo->pNext)
{
dwError = TDNFAllocateString(pPkgInfo->pszName, &ppszAutoInstalled[nCountOld++]);
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFStringArraySort(ppszAutoInstalled);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFJoinPath(&pszDataDir,
pTdnf->pArgs->pszInstallRoot,
TDNF_DEFAULT_DATA_LOCATION,
NULL);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFUtilsMakeDir(pszDataDir);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFJoinPath(&pszAutoFile,
pTdnf->pArgs->pszInstallRoot,
TDNF_DEFAULT_DATA_LOCATION,
TDNF_AUTOINSTALLED_FILE,
NULL);
BAIL_ON_TDNF_ERROR(dwError);
fp = fopen(pszAutoFile, "w");
if(!fp)
{
dwError = errno;
BAIL_ON_TDNF_SYSTEM_ERROR(dwError);
}
for (i = 0; ppszAutoInstalled[i]; i++)
{
if (i > 0 && strcmp(ppszAutoInstalled[i-1], ppszAutoInstalled[i]) == 0)
{
continue;
}
if (ppInfo->ppszPkgsUserInstall)
{
for (j = 0; ppInfo->ppszPkgsUserInstall[j]; j++)
{
if (strcmp(ppszAutoInstalled[i],
ppInfo->ppszPkgsUserInstall[j]) == 0)
{
break;
}
}
}
if (!ppInfo->ppszPkgsUserInstall || ppInfo->ppszPkgsUserInstall[j] == NULL)
{
fprintf(fp, "%s\n", ppszAutoInstalled[i]);
}
}
fclose(fp);
cleanup:
TDNF_SAFE_FREE_MEMORY(pszAutoFile);
TDNF_SAFE_FREE_STRINGARRAY(ppszAutoInstalled);
return dwError;
error:
if (fp)
{
fclose(fp);
}
goto cleanup;
}
uint32_t
TDNFAddGoal(
@ -521,6 +740,7 @@ TDNFAddGoal(
BAIL_ON_TDNF_ERROR(dwError);
break;
case ALTER_ERASE:
case ALTER_AUTOERASE:
dwError = SolvAddPkgEraseJob(pQueueJobs, dwId);
BAIL_ON_TDNF_ERROR(dwError);
break;
@ -530,10 +750,6 @@ TDNFAddGoal(
dwError = SolvAddPkgInstallJob(pQueueJobs, dwId);
BAIL_ON_TDNF_ERROR(dwError);
break;
case ALTER_AUTOERASE:
dwError = SolvAddPkgUserInstalledJob(pQueueJobs, dwId);
BAIL_ON_TDNF_ERROR(dwError);
break;
default:
dwError = ERROR_TDNF_INVALID_RESOLVE_ARG;
BAIL_ON_TDNF_ERROR(dwError);
@ -549,7 +765,6 @@ error:
uint32_t
TDNFGoalGetAllResultsIgnoreNoData(
int nResolveFor,
Transaction* pTrans,
Solver* pSolv,
PTDNF_SOLVED_PKG_INFO* ppInfo,
@ -596,14 +811,6 @@ TDNFGoalGetAllResultsIgnoreNoData(
&pInfo->pPkgsToRemove);
BAIL_ON_TDNF_ERROR(dwError);
if(nResolveFor == ALTER_AUTOERASE)
{
dwError = TDNFGetUnneededPackages(
pSolv,
pTdnf,
&pInfo->pPkgsUnNeeded);
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFGetReinstallPackages(
pTrans,
pTdnf,

View File

@ -57,6 +57,7 @@ TDNFCloneCmdArgs(
pCmdArgs->nIPv6 = pCmdArgsIn->nIPv6;
pCmdArgs->nDisableExcludes = pCmdArgsIn->nDisableExcludes;
pCmdArgs->nDownloadOnly = pCmdArgsIn->nDownloadOnly;
pCmdArgs->nNoAutoRemove = pCmdArgsIn->nNoAutoRemove;
dwError = TDNFAllocateString(
pCmdArgsIn->pszInstallRoot,

View File

@ -447,6 +447,25 @@ TDNFGoal(
TDNF_ALTERTYPE nAlterType
);
uint32_t
TDNFAddUserInstall(
PTDNF pTdnf,
Queue* pQueueGoal,
PTDNF_SOLVED_PKG_INFO ppInfo
);
uint32_t
TDNFMarkAutoInstalledSinglePkg(
PTDNF pTdnf,
const char *pszPkgName
);
uint32_t
TDNFMarkAutoInstalled(
PTDNF pTdnf,
PTDNF_SOLVED_PKG_INFO ppInfo
);
uint32_t
TDNFAddGoal(
PTDNF pTdnf,
@ -459,7 +478,6 @@ TDNFAddGoal(
uint32_t
TDNFGoalGetAllResultsIgnoreNoData(
int nResolveFor,
Transaction* pTrans,
Solver* pSolv,
PTDNF_SOLVED_PKG_INFO* ppInfo,
@ -1076,6 +1094,12 @@ TDNFGetCmdOpt(
PTDNF_CMD_OPT *ppOpt
);
uint32_t
TDNFReadAutoInstalled(
PTDNF pTdnf,
char ***pppszAutoInstalled
);
//validate.c
uint32_t
TDNFValidateCmdArgs(

View File

@ -84,10 +84,9 @@ TDNFPrepareAllPackages(
pCmdArgs = pTdnf->pArgs;
nAlterType = *pAlterType;
if(nAlterType == ALTER_DOWNGRADEALL ||
nAlterType == ALTER_AUTOERASE)
if(nAlterType == ALTER_DOWNGRADEALL)
{
dwError = TDNFFilterPackages(
dwError = TDNFFilterPackages(
pTdnf,
nAlterType,
ppszPkgsNotResolved,
@ -384,6 +383,12 @@ TDNFPrepareSinglePkg(
pSack,
queueGoal,
pszPkgName);
if (dwError == ERROR_TDNF_ALREADY_INSTALLED)
{
dwError = TDNFMarkAutoInstalledSinglePkg(pTdnf, pszPkgName);
BAIL_ON_TDNF_ERROR(dwError);
dwError = ERROR_TDNF_ALREADY_INSTALLED;
}
BAIL_ON_TDNF_ERROR(dwError);
}
else if (nAlterType == ALTER_UPGRADE)

View File

@ -102,6 +102,9 @@ TDNFRpmExecTransaction(
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFMarkAutoInstalled(pTdnf, pSolvedInfo);
BAIL_ON_TDNF_ERROR(dwError);
cleanup:
if(ts.pTS)
{

View File

@ -759,3 +759,41 @@ error:
return dwError;
}
uint32_t
TDNFReadAutoInstalled(
PTDNF pTdnf,
char ***pppszAutoInstalled
)
{
uint32_t dwError = 0;
char **ppszAutoInstalled = NULL;
char *pszAutoFile = NULL;
if (!pTdnf || !pppszAutoInstalled)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_ERROR(dwError);
}
dwError = TDNFAllocateStringPrintf(&pszAutoFile, "%s/%s/%s",
pTdnf->pArgs->pszInstallRoot,
TDNF_DEFAULT_DATA_LOCATION,
TDNF_AUTOINSTALLED_FILE);
BAIL_ON_TDNF_ERROR(dwError);
dwError = TDNFReadFileToStringArray(pszAutoFile, &ppszAutoInstalled);
if (dwError == ERROR_TDNF_SYSTEM_BASE + ENOENT)
{
dwError = 0;
}
BAIL_ON_TDNF_ERROR(dwError);
*pppszAutoInstalled = ppszAutoInstalled;
cleanup:
TDNF_SAFE_FREE_MEMORY(pszAutoFile);
return dwError;
error:
TDNF_SAFE_FREE_STRINGARRAY(ppszAutoInstalled);
goto cleanup;
}

View File

@ -260,7 +260,6 @@ TDNFFreeSolvedPackageInfo(
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo
)
{
int i = 0;
if(pSolvedPkgInfo)
{
TDNF_SAFE_FREE_PKGINFO(pSolvedPkgInfo->pPkgsNotAvailable);
@ -274,15 +273,8 @@ TDNFFreeSolvedPackageInfo(
TDNF_SAFE_FREE_PKGINFO(pSolvedPkgInfo->pPkgsObsoleted);
TDNF_SAFE_FREE_PKGINFO(pSolvedPkgInfo->pPkgsRemovedByDowngrade);
if(pSolvedPkgInfo->ppszPkgsNotResolved)
{
while(pSolvedPkgInfo->ppszPkgsNotResolved[i])
{
TDNF_SAFE_FREE_MEMORY(
pSolvedPkgInfo->ppszPkgsNotResolved[i++]);
}
}
TDNF_SAFE_FREE_MEMORY(pSolvedPkgInfo->ppszPkgsNotResolved);
TDNF_SAFE_FREE_STRINGARRAY(pSolvedPkgInfo->ppszPkgsNotResolved);
TDNF_SAFE_FREE_STRINGARRAY(pSolvedPkgInfo->ppszPkgsUserInstall);
}
TDNF_SAFE_FREE_MEMORY(pSolvedPkgInfo);
}

View File

@ -1,6 +1,5 @@
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=true
repodir=/etc/yum.repos.d
cachedir=/var/cache/tdnf

View File

@ -199,6 +199,7 @@ typedef struct _TDNF_SOLVED_PKG_INFO
PTDNF_PKG_INFO pPkgsObsoleted;
PTDNF_PKG_INFO pPkgsRemovedByDowngrade;
char** ppszPkgsNotResolved;
char** ppszPkgsUserInstall;
}TDNF_SOLVED_PKG_INFO, *PTDNF_SOLVED_PKG_INFO;
/*
@ -249,6 +250,7 @@ typedef struct _TDNF_CMD_ARGS
int nIPv6; //resolve to IPv6 addresses only
int nDisableExcludes; //disable excludes from tdnf.conf
int nDownloadOnly; //download packages only, no install
int nNoAutoRemove; //overide clean_requirements_on_remove config option
char* pszDownloadDir; //directory for download, if nDownloadOnly is set
char* pszInstallRoot; //set install root
char* pszConfFile; //set conf file location

View File

@ -444,6 +444,13 @@ SolvAddPkgUserInstalledJob(
Id dwId
);
uint32_t
SolvAddUserInstalledToJobs(
Queue* pQueueJobs,
Pool *pPool,
char **ppszAutoInstalled
);
uint32_t
SolvGetUpdateAdvisories(
PSolvSack pSack,

View File

@ -76,6 +76,61 @@ error:
goto cleanup;
}
uint32_t
SolvAddUserInstalledToJobs(
Queue* pQueueJobs,
Pool *pPool,
char **ppszAutoInstalled
)
{
uint32_t dwError = 0;
Id p;
Solvable *s;
Queue queueAutoInstalled = {0};
Id idAuto;
int i;
if(!pQueueJobs || !pPool)
{
dwError = ERROR_TDNF_INVALID_PARAMETER;
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
}
queue_init(&queueAutoInstalled);
if (ppszAutoInstalled)
{
for(i = 0; ppszAutoInstalled[i] != NULL; i++)
{
idAuto = pool_str2id(pPool, ppszAutoInstalled[i], 0);
if (idAuto)
{
queue_push(&queueAutoInstalled, idAuto);
}
}
}
FOR_REPO_SOLVABLES(pPool->installed, p, s)
{
for (i = 0; i < queueAutoInstalled.count; i++)
{
if (queueAutoInstalled.elements[i] == s->name)
{
break;
}
}
if (i >= queueAutoInstalled.count)
{
queue_push2(pQueueJobs, SOLVER_SOLVABLE_NAME|SOLVER_USERINSTALLED, s->name);
}
}
cleanup:
queue_free(&queueAutoInstalled);
return dwError;
error:
goto cleanup;
}
uint32_t
SolvAddPkgInstallJob(
Queue* pQueueJobs,

View File

@ -115,6 +115,7 @@ static struct option pstOptions[] =
{"disableexcludes", no_argument, &_opt.nDisableExcludes, 1}, //--disableexcludes
{"downloadonly", no_argument, &_opt.nDownloadOnly, 1}, //--downloadonly
{"downloaddir", required_argument, 0, 0}, //--downloaddir
{"noautoremove", no_argument, &_opt.nNoAutoRemove, 1},
// reposync options
{"arch", required_argument, 0, 0},
{"delete", no_argument, 0, 0},
@ -344,6 +345,7 @@ TDNFCopyOptions(
pArgs->nIPv6 = pOptionArgs->nIPv6;
pArgs->nDisableExcludes = pOptionArgs->nDisableExcludes;
pArgs->nDownloadOnly = pOptionArgs->nDownloadOnly;
pArgs->nNoAutoRemove = pOptionArgs->nNoAutoRemove;
cleanup:
return dwError;