mirror of https://github.com/vmware/tdnf.git
Merge pull request #248 from oliverkurth/topic/okurth/repoquery
implement the repoquery command
This commit is contained in:
commit
8445b0f0f8
170
client/api.c
170
client/api.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2018 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -1345,6 +1345,174 @@ error:
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFRepoQuery(
|
||||
PTDNF pTdnf,
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs,
|
||||
PTDNF_PKG_INFO* ppPkgInfo,
|
||||
uint32_t *pdwCount
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
PTDNF_PKG_INFO pPkgInfo = NULL;
|
||||
PSolvQuery pQuery = NULL;
|
||||
PSolvPackageList pPkgList = NULL;
|
||||
int nDetail;
|
||||
uint32_t dwCount = 0;
|
||||
TDNF_SCOPE nScope = SCOPE_ALL;
|
||||
|
||||
if(!pTdnf || !pTdnf->pSack || !pRepoqueryArgs ||
|
||||
!ppPkgInfo || !pdwCount)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* check if args make sense. extra packages are installed by definition */
|
||||
if (pRepoqueryArgs->nExtras &&
|
||||
(pRepoqueryArgs->nInstalled || pRepoqueryArgs->nAvailable ||
|
||||
pRepoqueryArgs->nDuplicates))
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* duplicate packages are also installed by definition */
|
||||
if (pRepoqueryArgs->nDuplicates &&
|
||||
(pRepoqueryArgs->nInstalled || pRepoqueryArgs->nAvailable))
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFRefresh(pTdnf);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
/* handle select options */
|
||||
|
||||
dwError = SolvCreateQuery(pTdnf->pSack, &pQuery);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
if (!pRepoqueryArgs->nExtras)
|
||||
{
|
||||
if (!pRepoqueryArgs->nInstalled || pRepoqueryArgs->nAvailable)
|
||||
{
|
||||
nScope = SCOPE_AVAILABLE;
|
||||
}
|
||||
else if (pRepoqueryArgs->nInstalled || pRepoqueryArgs->nDuplicates)
|
||||
{
|
||||
nScope = SCOPE_INSTALLED;
|
||||
}
|
||||
else if(pRepoqueryArgs->nUpgrades)
|
||||
{
|
||||
nScope = SCOPE_UPGRADES;
|
||||
}
|
||||
}
|
||||
dwError = TDNFApplyScopeFilter(pQuery, nScope);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
/* filter for package(s) given as arguments, if any */
|
||||
if (pRepoqueryArgs->pszSpec)
|
||||
{
|
||||
dwError = SolvApplySinglePackageFilter(pQuery, pRepoqueryArgs->pszSpec);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* run all the filters */
|
||||
dwError = SolvApplyListQuery(pQuery);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
/* now filter for extras or duplicates */
|
||||
if (pRepoqueryArgs->nExtras)
|
||||
{
|
||||
dwError = SolvApplyExtrasFilter(pQuery);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
else if (pRepoqueryArgs->nDuplicates)
|
||||
{
|
||||
dwError = SolvApplyDuplicatesFilter(pQuery);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* filter for package(s) that depend on give package(s) */
|
||||
if (pRepoqueryArgs->pppszWhatKeys)
|
||||
{
|
||||
REPOQUERY_WHAT_KEY whatKey;
|
||||
|
||||
for (whatKey = 0; whatKey < REPOQUERY_WHAT_KEY_COUNT; whatKey++)
|
||||
{
|
||||
if (pRepoqueryArgs->pppszWhatKeys[whatKey])
|
||||
{
|
||||
dwError = SolvApplyDepsFilter(pQuery,
|
||||
pRepoqueryArgs->pppszWhatKeys[whatKey],
|
||||
whatKey);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* filter for package(s) that provide a given file */
|
||||
if (pRepoqueryArgs->pszFile)
|
||||
{
|
||||
dwError = SolvApplyFileProvidesFilter(pQuery, pRepoqueryArgs->pszFile);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* get results in list */
|
||||
dwError = SolvGetQueryResult(pQuery, &pPkgList);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
/* handle query options */
|
||||
|
||||
/* TDNFPopulatePkgInfoArray fills in details */
|
||||
nDetail = pRepoqueryArgs->nChangeLogs ? DETAIL_CHANGELOG :
|
||||
pRepoqueryArgs->nSource ? DETAIL_SOURCEPKG :
|
||||
DETAIL_LIST;
|
||||
dwError = TDNFPopulatePkgInfoArray(pTdnf->pSack, pPkgList, nDetail,
|
||||
&pPkgInfo, &dwCount);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
/* fill in file list or dependencies */
|
||||
if (pRepoqueryArgs->nList)
|
||||
{
|
||||
dwError = TDNFPopulatePkgInfoArrayFileList(
|
||||
pTdnf->pSack,
|
||||
pPkgList,
|
||||
pPkgInfo);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
else if (pRepoqueryArgs->depKey)
|
||||
{
|
||||
dwError = TDNFPopulatePkgInfoArrayDependencies(
|
||||
pTdnf->pSack,
|
||||
pPkgList,
|
||||
pRepoqueryArgs->depKey,
|
||||
pPkgInfo);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
*ppPkgInfo = pPkgInfo;
|
||||
*pdwCount = dwCount;
|
||||
|
||||
cleanup:
|
||||
if(pQuery)
|
||||
{
|
||||
SolvFreeQuery(pQuery);
|
||||
}
|
||||
if(pPkgList)
|
||||
{
|
||||
SolvFreePackageList(pPkgList);
|
||||
}
|
||||
return dwError;
|
||||
error:
|
||||
TDNFFreePackageInfo(pPkgInfo);
|
||||
if(dwError == ERROR_TDNF_NO_MATCH)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//Resolve alter command before presenting
|
||||
//the goal steps to user for approval
|
||||
uint32_t
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
|
||||
typedef enum
|
||||
{
|
||||
/* this should be a bitmask */
|
||||
DETAIL_LIST,
|
||||
DETAIL_INFO
|
||||
DETAIL_INFO,
|
||||
DETAIL_CHANGELOG,
|
||||
DETAIL_SOURCEPKG
|
||||
}TDNF_PKG_DETAIL;
|
||||
|
||||
#define BAIL_ON_TDNF_RPM_ERROR(dwError) \
|
||||
|
@ -56,6 +59,7 @@ typedef enum
|
|||
#define TDNF_REPOMD_TYPE_PRIMARY "primary"
|
||||
#define TDNF_REPOMD_TYPE_FILELISTS "filelists"
|
||||
#define TDNF_REPOMD_TYPE_UPDATEINFO "updateinfo"
|
||||
#define TDNF_REPOMD_TYPE_OTHER "other"
|
||||
|
||||
//Repo defines
|
||||
#define TDNF_REPO_EXT ".repo"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -93,10 +93,13 @@ TDNFPopulatePkgInfoArray(
|
|||
{
|
||||
uint32_t dwError = 0;
|
||||
uint32_t dwCount = 0;
|
||||
int dwPkgIndex = 0;
|
||||
uint32_t dwPkgIndex = 0;
|
||||
Id dwPkgId = 0;
|
||||
PTDNF_PKG_INFO pPkgInfos = NULL;
|
||||
PTDNF_PKG_INFO pPkgInfo = NULL;
|
||||
char *pszSrcName = NULL;
|
||||
char *pszSrcArch = NULL;
|
||||
char *pszSrcEVR = NULL;
|
||||
|
||||
if(!ppPkgInfo || !pdwCount || !pSack || !pPkgList)
|
||||
{
|
||||
|
@ -184,12 +187,43 @@ TDNFPopulatePkgInfoArray(
|
|||
&pPkgInfo->pszDescription);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
else if (nDetail == DETAIL_CHANGELOG)
|
||||
{
|
||||
dwError = SolvGetChangeLogFromId(
|
||||
pSack,
|
||||
dwPkgId,
|
||||
&pPkgInfo->pChangeLogEntries);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
else if (nDetail == DETAIL_SOURCEPKG)
|
||||
{
|
||||
dwError = SolvGetSourceFromId(
|
||||
pSack,
|
||||
dwPkgId,
|
||||
&pszSrcName,
|
||||
&pszSrcArch,
|
||||
&pszSrcEVR);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dwError = TDNFAllocateStringPrintf(
|
||||
&pPkgInfo->pszSourcePkg,
|
||||
"%s-%s.%s",
|
||||
pszSrcName, pszSrcEVR, pszSrcArch);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
if (dwPkgIndex < dwCount - 1)
|
||||
{
|
||||
pPkgInfo->pNext = &pPkgInfos[dwPkgIndex+1];
|
||||
}
|
||||
}
|
||||
|
||||
*pdwCount = dwCount;
|
||||
*ppPkgInfo = pPkgInfos;
|
||||
|
||||
cleanup:
|
||||
TDNF_SAFE_FREE_MEMORY(pszSrcName);
|
||||
TDNF_SAFE_FREE_MEMORY(pszSrcArch);
|
||||
TDNF_SAFE_FREE_MEMORY(pszSrcEVR);
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
|
@ -362,7 +396,7 @@ TDNFPkgInfoFilterNewest(
|
|||
older versions of the same packages. The linked list will only
|
||||
touch the newest (first) version of a package.
|
||||
The same package in different repos will be handled as two different
|
||||
packages. */
|
||||
packages. */
|
||||
pPkgInfo = ppPkgInfos[0];
|
||||
for (i = 1; i < dwCount; i++)
|
||||
{
|
||||
|
@ -1084,3 +1118,97 @@ error:
|
|||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFPopulatePkgInfoArrayDependencies(
|
||||
PSolvSack pSack,
|
||||
PSolvPackageList pPkgList,
|
||||
REPOQUERY_DEP_KEY depKey,
|
||||
PTDNF_PKG_INFO pPkgInfos
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
uint32_t dwCount = 0;
|
||||
uint32_t dwPkgIndex = 0;
|
||||
Id dwPkgId = 0;
|
||||
PTDNF_PKG_INFO pPkgInfo = NULL;
|
||||
|
||||
if(!pPkgInfos || !pSack || !pPkgList)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = SolvGetPackageListSize(pPkgList, &dwCount);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
if(dwCount == 0)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_MATCH;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
for (dwPkgIndex = 0; dwPkgIndex < dwCount; dwPkgIndex++)
|
||||
{
|
||||
pPkgInfo = &pPkgInfos[dwPkgIndex];
|
||||
|
||||
dwError = SolvGetPackageId(pPkgList, dwPkgIndex, &dwPkgId);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dwError = SolvGetDependenciesFromId(pSack, dwPkgId, depKey, &pPkgInfo->ppszDependencies);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFPopulatePkgInfoArrayFileList(
|
||||
PSolvSack pSack,
|
||||
PSolvPackageList pPkgList,
|
||||
PTDNF_PKG_INFO pPkgInfos
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
uint32_t dwCount = 0;
|
||||
uint32_t dwPkgIndex = 0;
|
||||
Id dwPkgId = 0;
|
||||
PTDNF_PKG_INFO pPkgInfo = NULL;
|
||||
|
||||
if(!pPkgInfos || !pSack || !pPkgList)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = SolvGetPackageListSize(pPkgList, &dwCount);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
if(dwCount == 0)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_MATCH;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
for (dwPkgIndex = 0; dwPkgIndex < dwCount; dwPkgIndex++)
|
||||
{
|
||||
pPkgInfo = &pPkgInfos[dwPkgIndex];
|
||||
|
||||
dwError = SolvGetPackageId(pPkgList, dwPkgIndex, &dwPkgId);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dwError = SolvGetFileListFromId(pSack, dwPkgId, &pPkgInfo->ppszFileList);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -430,6 +430,21 @@ TDNFCheckMinVersions(
|
|||
PTDNF_SOLVED_PKG_INFO pSolvedPkgInfo
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFPopulatePkgInfoArrayDependencies(
|
||||
PSolvSack pSack,
|
||||
PSolvPackageList pPkgList,
|
||||
REPOQUERY_DEP_KEY depKey,
|
||||
PTDNF_PKG_INFO pPkgInfos
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFPopulatePkgInfoArrayFileList(
|
||||
PSolvSack pSack,
|
||||
PSolvPackageList pPkgList,
|
||||
PTDNF_PKG_INFO pPkgInfos
|
||||
);
|
||||
|
||||
//goal.c
|
||||
uint32_t
|
||||
TDNFGoal(
|
||||
|
|
|
@ -160,7 +160,8 @@ TDNFInitRepoFromMetadata(
|
|||
pRepoMD->pszRepoMD,
|
||||
pRepoMD->pszPrimary,
|
||||
pRepoMD->pszFileLists,
|
||||
pRepoMD->pszUpdateInfo);
|
||||
pRepoMD->pszUpdateInfo,
|
||||
pRepoMD->pszOther);
|
||||
cleanup:
|
||||
return dwError;
|
||||
|
||||
|
@ -942,7 +943,8 @@ TDNFGetRepoMD(
|
|||
|
||||
if (nReplaceRepoMD)
|
||||
{
|
||||
/* Remove the old repodata, solvcache and lastRefreshMarker before replacing the new repomd file and metalink files. */
|
||||
/* Remove the old repodata, solvcache and lastRefreshMarker before
|
||||
replacing the new repomd file and metalink files. */
|
||||
TDNFRepoRemoveCache(pTdnf, pRepoData->pszId);
|
||||
TDNFRemoveSolvCache(pTdnf, pRepoData->pszId);
|
||||
TDNFRemoveLastRefreshMarker(pTdnf, pRepoData->pszId);
|
||||
|
@ -1137,6 +1139,23 @@ TDNFEnsureRepoMDParts(
|
|||
pRepoMD->pszUpdateInfo);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
if(!IsNullOrEmptyString(pRepoMDRel->pszOther))
|
||||
{
|
||||
dwError = TDNFAppendPath(
|
||||
pRepoMDRel->pszRepoCacheDir,
|
||||
pRepoMDRel->pszOther,
|
||||
&pRepoMD->pszOther);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dwError = TDNFDownloadRepoMDPart(
|
||||
pTdnf,
|
||||
pszBaseUrl,
|
||||
pRepoMDRel->pszRepo,
|
||||
pRepoMDRel->pszOther,
|
||||
pRepoMD->pszOther);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
*ppRepoMD = pRepoMD;
|
||||
|
||||
cleanup:
|
||||
|
@ -1272,6 +1291,16 @@ TDNFParseRepoMD(
|
|||
}
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dwError = TDNFFindRepoMDPart(
|
||||
pRepo,
|
||||
TDNF_REPOMD_TYPE_OTHER,
|
||||
&pRepoMD->pszOther);
|
||||
if(dwError == ERROR_TDNF_NO_DATA)
|
||||
{
|
||||
dwError = 0;
|
||||
}
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
cleanup:
|
||||
if (fp)
|
||||
{
|
||||
|
@ -1306,6 +1335,7 @@ TDNFFreeRepoMetadata(
|
|||
TDNF_SAFE_FREE_MEMORY(pRepoMD->pszPrimary);
|
||||
TDNF_SAFE_FREE_MEMORY(pRepoMD->pszFileLists);
|
||||
TDNF_SAFE_FREE_MEMORY(pRepoMD->pszUpdateInfo);
|
||||
TDNF_SAFE_FREE_MEMORY(pRepoMD->pszOther);
|
||||
TDNF_SAFE_FREE_MEMORY(pRepoMD);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef struct _TDNF_REPO_METADATA
|
|||
char *pszPrimary;
|
||||
char *pszFileLists;
|
||||
char *pszUpdateInfo;
|
||||
char *pszOther;
|
||||
}TDNF_REPO_METADATA,*PTDNF_REPO_METADATA;
|
||||
|
||||
typedef struct _TDNF_EVENT_DATA_
|
||||
|
|
|
@ -124,6 +124,11 @@ TDNFStringArrayCount(
|
|||
int *pnCount
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFStringArraySort(
|
||||
char **ppszArray
|
||||
);
|
||||
|
||||
//configreader.c
|
||||
void
|
||||
TDNFPrintConfigData(
|
||||
|
|
|
@ -524,3 +524,33 @@ error:
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
static int
|
||||
_cmpstringp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcmp(* (char * const *) p1, * (char * const *) p2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFStringArraySort(
|
||||
char **ppszArray
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
int nCount;
|
||||
|
||||
if (IsNullOrEmptyString(ppszArray))
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
for(nCount = 0; ppszArray[nCount]; nCount++);
|
||||
|
||||
qsort(ppszArray, nCount, sizeof(char *), _cmpstringp);
|
||||
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2018 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -209,11 +209,26 @@ TDNFFreePackageInfoArray(
|
|||
TDNF_SAFE_FREE_MEMORY(pPkgInfoArray);
|
||||
}
|
||||
|
||||
void
|
||||
TDNFFreeChangeLogEntry(
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntry
|
||||
)
|
||||
{
|
||||
if (pEntry)
|
||||
{
|
||||
TDNF_SAFE_FREE_MEMORY(pEntry->pszAuthor);
|
||||
TDNF_SAFE_FREE_MEMORY(pEntry->pszText);
|
||||
TDNF_SAFE_FREE_MEMORY(pEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TDNFFreePackageInfoContents(
|
||||
PTDNF_PKG_INFO pPkgInfo
|
||||
)
|
||||
{
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntry, pEntryNext;
|
||||
|
||||
if(pPkgInfo)
|
||||
{
|
||||
TDNF_SAFE_FREE_MEMORY(pPkgInfo->pszName);
|
||||
|
@ -228,6 +243,15 @@ TDNFFreePackageInfoContents(
|
|||
TDNF_SAFE_FREE_MEMORY(pPkgInfo->pszFormattedSize);
|
||||
TDNF_SAFE_FREE_MEMORY(pPkgInfo->pszRelease);
|
||||
TDNF_SAFE_FREE_MEMORY(pPkgInfo->pszLocation);
|
||||
TDNF_SAFE_FREE_STRINGARRAY(pPkgInfo->ppszDependencies);
|
||||
TDNF_SAFE_FREE_STRINGARRAY(pPkgInfo->ppszFileList);
|
||||
for (pEntry = pPkgInfo->pChangeLogEntries;
|
||||
pEntry;
|
||||
pEntry = pEntryNext)
|
||||
{
|
||||
pEntryNext = pEntry->pNext;
|
||||
TDNFFreeChangeLogEntry(pEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,13 +113,22 @@ TDNFProvides(
|
|||
PTDNF_PKG_INFO* ppPkgInfo
|
||||
);
|
||||
|
||||
//query repo
|
||||
//sync repo
|
||||
uint32_t
|
||||
TDNFRepoSync(
|
||||
PTDNF pTdnf,
|
||||
PTDNF_REPOSYNC_ARGS pReposyncArgs
|
||||
);
|
||||
|
||||
//query repo
|
||||
uint32_t
|
||||
TDNFRepoQuery(
|
||||
PTDNF pTdnf,
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs,
|
||||
PTDNF_PKG_INFO* ppPkgInfo,
|
||||
uint32_t *pdwCount
|
||||
);
|
||||
|
||||
//Show update info for specified scope
|
||||
uint32_t
|
||||
TDNFUpdateInfo(
|
||||
|
@ -223,6 +232,11 @@ TDNFFreePackageInfoArray(
|
|||
uint32_t dwLength
|
||||
);
|
||||
|
||||
void
|
||||
TDNFFreeChangeLogEntry(
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntry
|
||||
);
|
||||
|
||||
void
|
||||
TDNFFreeRepos(
|
||||
PTDNF_REPO_DATA pRepos
|
||||
|
|
|
@ -77,6 +77,12 @@ TDNFCliParseRepoSyncArgs(
|
|||
PTDNF_REPOSYNC_ARGS* ppReposyncArgs
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliParseRepoQueryArgs(
|
||||
PTDNF_CMD_ARGS pCmdArgs,
|
||||
PTDNF_REPOQUERY_ARGS* ppRepoqueryArgs
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliParseMode(
|
||||
const char* pszOutMode,
|
||||
|
@ -127,6 +133,11 @@ TDNFCliFreeRepoSyncArgs(
|
|||
PTDNF_REPOSYNC_ARGS pReposyncArgs
|
||||
);
|
||||
|
||||
void
|
||||
TDNFCliFreeRepoQueryArgs(
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs
|
||||
);
|
||||
|
||||
//Commands
|
||||
uint32_t
|
||||
TDNFCliAutoEraseCommand(
|
||||
|
@ -206,6 +217,12 @@ TDNFCliRepoSyncCommand(
|
|||
PTDNF_CMD_ARGS pCmdArgs
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliRepoQueryCommand(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
PTDNF_CMD_ARGS pCmdArgs
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliUpdateInfoCommand(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
|
|
|
@ -23,5 +23,6 @@
|
|||
#define ERROR_TDNF_CLI_SETOPT_NO_EQUALS (ERROR_TDNF_CLI_BASE + 11)
|
||||
#define ERROR_TDNF_CLI_NO_SUCH_CMD (ERROR_TDNF_CLI_BASE + 12)
|
||||
#define ERROR_TDNF_CLI_DOWNLOADDIR_REQUIRES_DOWNLOADONLY (ERROR_TDNF_CLI_BASE + 13)
|
||||
#define ERROR_TDNF_CLI_ONE_DEP_ONLY (ERROR_TDNF_CLI_BASE + 14)
|
||||
|
||||
#endif /* __TDNF_CLI_ERR_H__ */
|
||||
|
|
|
@ -113,6 +113,14 @@ typedef uint32_t
|
|||
PTDNF_REPOSYNC_ARGS
|
||||
);
|
||||
|
||||
typedef uint32_t
|
||||
(*PFN_TDNF_REPOQUERY)(
|
||||
PTDNF_CLI_CONTEXT,
|
||||
PTDNF_REPOQUERY_ARGS,
|
||||
PTDNF_PKG_INFO *,
|
||||
uint32_t *
|
||||
);
|
||||
|
||||
typedef uint32_t
|
||||
(*PFN_TDNF_RESOLVE)(
|
||||
PTDNF_CLI_CONTEXT,
|
||||
|
@ -155,6 +163,7 @@ typedef struct _TDNF_CLI_CONTEXT_
|
|||
PFN_TDNF_PROVIDES pFnProvides;
|
||||
PFN_TDNF_REPOLIST pFnRepoList;
|
||||
PFN_TDNF_REPOSYNC pFnRepoSync;
|
||||
PFN_TDNF_REPOQUERY pFnRepoQuery;
|
||||
PFN_TDNF_RESOLVE pFnResolve;
|
||||
PFN_TDNF_SEARCH pFnSearch;
|
||||
PFN_TDNF_UPDATEINFO pFnUpdateInfo;
|
||||
|
|
|
@ -152,6 +152,14 @@ typedef enum
|
|||
|
||||
typedef struct _TDNF_ *PTDNF;
|
||||
|
||||
typedef struct _TDNF_PKG_CHANGELOG_ENTRY
|
||||
{
|
||||
time_t timeTime;
|
||||
char *pszAuthor;
|
||||
char *pszText;
|
||||
struct _TDNF_PKG_CHANGELOG_ENTRY *pNext;
|
||||
} TDNF_PKG_CHANGELOG_ENTRY, *PTDNF_PKG_CHANGELOG_ENTRY;
|
||||
|
||||
typedef struct _TDNF_PKG_INFO
|
||||
{
|
||||
uint32_t dwEpoch;
|
||||
|
@ -168,6 +176,10 @@ typedef struct _TDNF_PKG_INFO
|
|||
char* pszFormattedSize;
|
||||
char* pszRelease;
|
||||
char* pszLocation;
|
||||
char **ppszDependencies;
|
||||
char **ppszFileList;
|
||||
char *pszSourcePkg;
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pChangeLogEntries;
|
||||
struct _TDNF_PKG_INFO* pNext;
|
||||
}TDNF_PKG_INFO, *PTDNF_PKG_INFO;
|
||||
|
||||
|
@ -351,6 +363,54 @@ typedef struct _TDNF_REPOSYNC_ARGS
|
|||
char **ppszArchs;
|
||||
}TDNF_REPOSYNC_ARGS, *PTDNF_REPOSYNC_ARGS;
|
||||
|
||||
typedef enum {
|
||||
REPOQUERY_WHAT_KEY_PROVIDES,
|
||||
REPOQUERY_WHAT_KEY_OBSOLETES,
|
||||
REPOQUERY_WHAT_KEY_CONFLICTS,
|
||||
REPOQUERY_WHAT_KEY_REQUIRES,
|
||||
REPOQUERY_WHAT_KEY_RECOMMENDS,
|
||||
REPOQUERY_WHAT_KEY_SUGGESTS,
|
||||
REPOQUERY_WHAT_KEY_SUPPLEMENTS,
|
||||
REPOQUERY_WHAT_KEY_ENHANCES,
|
||||
REPOQUERY_WHAT_KEY_DEPENDS,
|
||||
REPOQUERY_WHAT_KEY_COUNT
|
||||
} REPOQUERY_WHAT_KEY;
|
||||
|
||||
typedef enum {
|
||||
REPOQUERY_DEP_KEY_NONE = 0,
|
||||
REPOQUERY_DEP_KEY_PROVIDES,
|
||||
REPOQUERY_DEP_KEY_OBSOLETES,
|
||||
REPOQUERY_DEP_KEY_CONFLICTS,
|
||||
REPOQUERY_DEP_KEY_REQUIRES,
|
||||
REPOQUERY_DEP_KEY_RECOMMENDS,
|
||||
REPOQUERY_DEP_KEY_SUGGESTS,
|
||||
REPOQUERY_DEP_KEY_SUPPLEMENTS,
|
||||
REPOQUERY_DEP_KEY_ENHANCES,
|
||||
REPOQUERY_DEP_KEY_DEPENDS,
|
||||
REPOQUERY_DEP_KEY_REQUIRES_PRE,
|
||||
REPOQUERY_DEP_KEY_COUNT
|
||||
} REPOQUERY_DEP_KEY;
|
||||
|
||||
typedef struct _TDNF_REPOQUERY_ARGS
|
||||
{
|
||||
char *pszSpec;
|
||||
|
||||
/* select options */
|
||||
int nAvailable; /* list what's available (default) */
|
||||
int nDuplicates;
|
||||
int nExtras; /* packages that are installed but not available */
|
||||
int nInstalled;
|
||||
int nUpgrades;
|
||||
char *pszFile; /* packages that own this file */
|
||||
char ***pppszWhatKeys;
|
||||
|
||||
/* query options */
|
||||
int nChangeLogs;
|
||||
REPOQUERY_DEP_KEY depKey; /* list dependencies of this type, 0 => unset */
|
||||
int nList; /* list files of packages(s) */
|
||||
int nSource; /* show source packages */
|
||||
}TDNF_REPOQUERY_ARGS, *PTDNF_REPOQUERY_ARGS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -54,6 +54,10 @@ cat << EOF > ~/.rpmmacros
|
|||
%__gpg /usr/bin/gpg
|
||||
EOF
|
||||
|
||||
for d in conflicts enhances obsoletes provides recommends requires suggests supplements ; do
|
||||
sed s/@@dep@@/$d/ < ${REPO_SRC_DIR}/tdnf-repoquery-deps.spec.in > ${REPO_SRC_DIR}/tdnf-repoquery-$d.spec
|
||||
done
|
||||
|
||||
echo building packages
|
||||
rpmbuild --define "_topdir ${BUILD_PATH}" \
|
||||
-r ${BUILD_PATH} -ba ${REPO_SRC_DIR}/*.spec
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
Summary: Repoquery Test
|
||||
Name: tdnf-repoquery-base
|
||||
Version: 1.0.1
|
||||
Release: 2
|
||||
Vendor: VMware, Inc.
|
||||
Distribution: Photon
|
||||
License: VMware
|
||||
Url: http://www.vmware.com
|
||||
Group: Applications/tdnftest
|
||||
|
||||
%description
|
||||
Part of tdnf test spec. For repoquery tests, other packages will
|
||||
depend on this in some way.
|
||||
|
||||
%prep
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
mkdir -p %_topdir/%buildroot/usr/lib/repoquery
|
||||
touch %_topdir/%buildroot/usr/lib/repoquery/%name
|
||||
%files
|
||||
/usr/lib/repoquery/%name
|
||||
|
||||
%changelog
|
||||
* Tue Jul 06 2021 Oliver Kurth <okurth@vmware.com> 1.0.1-2
|
||||
- first repoquery version
|
|
@ -0,0 +1,30 @@
|
|||
Summary: Repoquery Test
|
||||
Name: tdnf-repoquery-changelog
|
||||
Version: 1.0.1
|
||||
Release: 2
|
||||
Vendor: VMware, Inc.
|
||||
Distribution: Photon
|
||||
License: VMware
|
||||
Url: http://www.vmware.com
|
||||
Group: Applications/tdnftest
|
||||
|
||||
%description
|
||||
Part of tdnf test spec. For repoquery tests, other packages will
|
||||
depend on this in some way.
|
||||
|
||||
%prep
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
mkdir -p %_topdir/%buildroot/usr/lib/repoquery
|
||||
touch %_topdir/%buildroot/usr/lib/repoquery/%name
|
||||
%files
|
||||
/usr/lib/repoquery/%name
|
||||
|
||||
%changelog
|
||||
* Tue Jul 06 2021 Oliver Kurth <okurth@vmware.com> 1.2.3-4
|
||||
- needle in a haystack
|
||||
* Wed Jan 01 2020 John Doe <jdoe@jdoe.com> 1.0.0-1
|
||||
- wrong date, needed for testing. Fedora ignores dates before
|
||||
some time 2018.
|
|
@ -0,0 +1,29 @@
|
|||
Summary: Repoquery Test
|
||||
Name: tdnf-repoquery-@@dep@@
|
||||
Version: 1.0.1
|
||||
Release: 2
|
||||
Vendor: VMware, Inc.
|
||||
Distribution: Photon
|
||||
License: VMware
|
||||
Url: http://www.vmware.com
|
||||
Group: Applications/tdnftest
|
||||
|
||||
@@dep@@: tdnf-repoquery-base
|
||||
|
||||
%description
|
||||
Part of tdnf test spec. For repoquery tests, this package will
|
||||
depend on tdnf-repoquery-base (or provide, ...)
|
||||
|
||||
%prep
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
mkdir -p %_topdir/%buildroot/usr/lib/repoquery
|
||||
touch %_topdir/%buildroot/usr/lib/repoquery/%name
|
||||
%files
|
||||
/usr/lib/repoquery/%name
|
||||
|
||||
%changelog
|
||||
* Tue Jul 06 2021 Oliver Kurth <okurth@vmware.com> 1.0.1-2
|
||||
- first repoquery version
|
|
@ -0,0 +1,200 @@
|
|||
#
|
||||
# Copyright (C) 2021 VMware, Inc. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the GNU General Public License v2 (the "License");
|
||||
# you may not use this file except in compliance with the License. The terms
|
||||
# of the License are located in the COPYING file of this distribution.
|
||||
#
|
||||
# Author: Oliver Kurth <okurth@vmware.com>
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import errno
|
||||
import pytest
|
||||
|
||||
BASE_PKG = 'tdnf-repoquery-base'
|
||||
|
||||
@pytest.fixture(scope='function', autouse=True)
|
||||
def setup_test(utils):
|
||||
yield
|
||||
teardown_test(utils)
|
||||
|
||||
def teardown_test(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'remove', '-y',
|
||||
BASE_PKG])
|
||||
|
||||
# repoquery should list all packages that depend on BASE_PKG
|
||||
# (one of 'enhances', 'recommends', 'requires', 'suggests', 'supplements')
|
||||
def test_whatdepends(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--whatdepends',
|
||||
BASE_PKG])
|
||||
assert(ret['retval'] == 0)
|
||||
|
||||
for d in ['enhances', 'recommends', 'requires', 'suggests', 'supplements']:
|
||||
assert('tdnf-repoquery-{}'.format(d) in '\n'.join(ret['stdout']))
|
||||
|
||||
# repoquery should list the package that has a specific
|
||||
# relation to BASE_PKG
|
||||
def test_what_alldeps(utils):
|
||||
dep_types = ['conflicts', 'enhances', 'obsoletes', 'provides',
|
||||
'recommends', 'requires', 'suggests', 'supplements']
|
||||
|
||||
for dep in dep_types:
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--what{}'.format(dep),
|
||||
BASE_PKG
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
assert('tdnf-repoquery-{}'.format(dep) in '\n'.join(ret['stdout']))
|
||||
|
||||
# repoquery should list the package that requires BASE_PKG
|
||||
# or some other package that may or may not exist. Tests multiple
|
||||
# args to --whatrequires separated by a comma
|
||||
def test_what_2(utils):
|
||||
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--whatrequires',
|
||||
"{},{}".format('doesnotexist', BASE_PKG)
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
assert('tdnf-repoquery-requires' in '\n'.join(ret['stdout']))
|
||||
|
||||
# packages should have specified relation to BASE_PKG
|
||||
def test_alldeps(utils):
|
||||
dep_types = ['conflicts', 'enhances', 'obsoletes', 'provides',
|
||||
'recommends', 'requires', 'suggests', 'supplements']
|
||||
|
||||
for dep in dep_types:
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--{}'.format(dep),
|
||||
'tdnf-repoquery-{}'.format(dep)
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
assert(BASE_PKG in '\n'.join(ret['stdout']))
|
||||
|
||||
# all these packages depend on BASE_PKG
|
||||
def test_depends(utils):
|
||||
for dep in ['enhances', 'recommends', 'requires', 'suggests', 'supplements']:
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--depends',
|
||||
'tdnf-repoquery-{}'.format(dep)])
|
||||
assert(ret['retval'] == 0)
|
||||
assert(BASE_PKG in '\n'.join(ret['stdout']))
|
||||
|
||||
# each package has a file with its name
|
||||
def test_list(utils):
|
||||
dep_types = ['conflicts', 'enhances', 'obsoletes', 'provides',
|
||||
'recommends', 'requires', 'suggests', 'supplements']
|
||||
|
||||
for dep in dep_types:
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--list',
|
||||
'tdnf-repoquery-{}'.format(dep)
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
assert('/usr/lib/repoquery/tdnf-repoquery-{}'.format(dep) in '\n'.join(ret['stdout']))
|
||||
|
||||
# like test_list(), but the other way around
|
||||
def test_file(utils):
|
||||
dep_types = ['conflicts', 'enhances', 'obsoletes', 'provides',
|
||||
'recommends', 'requires', 'suggests', 'supplements']
|
||||
|
||||
for dep in dep_types:
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--file',
|
||||
'/usr/lib/repoquery/tdnf-repoquery-{}'.format(dep)
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
assert('tdnf-repoquery-{}'.format(dep) in '\n'.join(ret['stdout']))
|
||||
|
||||
def test_available(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--available'])
|
||||
assert(ret['retval'] == 0)
|
||||
assert(BASE_PKG in '\n'.join(ret['stdout']))
|
||||
|
||||
def test_installed(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'install', '-y', '--nogpgcheck',
|
||||
BASE_PKG])
|
||||
assert(ret['retval'] == 0)
|
||||
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--installed'])
|
||||
assert(ret['retval'] == 0)
|
||||
assert(BASE_PKG in '\n'.join(ret['stdout']))
|
||||
|
||||
def test_extras(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--extras'])
|
||||
assert(ret['retval'] == 0)
|
||||
# we are using just the 'photon-test repo,
|
||||
# so any real system package is 'extra'
|
||||
assert('glibc' in '\n'.join(ret['stdout']))
|
||||
|
||||
def test_upgrades(utils):
|
||||
pkg_low = "{}-{}".format(utils.config["mulversion_pkgname"], utils.config["mulversion_lower"])
|
||||
pkg_high = "{}-{}".format(utils.config["mulversion_pkgname"], utils.config["mulversion_higher"])
|
||||
|
||||
ret = utils.run(['tdnf',
|
||||
'install', '-y', '--nogpgcheck',
|
||||
pkg_low])
|
||||
assert(ret['retval'] == 0)
|
||||
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--upgrades'])
|
||||
assert(ret['retval'] == 0)
|
||||
assert(pkg_high in '\n'.join(ret['stdout']))
|
||||
|
||||
def test_changelog(utils):
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--changelogs',
|
||||
'tdnf-repoquery-changelog'])
|
||||
assert(ret['retval'] == 0)
|
||||
|
||||
# tests changelog text, author and date
|
||||
output = '\n'.join(ret['stdout'])
|
||||
assert("needle in a haystack" in output)
|
||||
assert("John Doe" in output)
|
||||
assert("Wed Jan 01 2020" in output)
|
||||
|
||||
def test_source(utils):
|
||||
# any package should do that has
|
||||
# the same name as the source
|
||||
pkgname = 'tdnf-repoquery-base'
|
||||
|
||||
ret = utils.run(['tdnf',
|
||||
'repoquery',
|
||||
'--source',
|
||||
pkgname])
|
||||
assert(ret['retval'] == 0)
|
||||
output = '\n'.join(ret['stdout'])
|
||||
assert(pkgname in output)
|
||||
assert('src' in output)
|
||||
assert(not 'x86_64' in output)
|
||||
|
||||
# each package has a file with its name
|
||||
def test_list(utils):
|
||||
|
||||
dep = 'requires'
|
||||
ret = utils.run_memcheck(['tdnf',
|
||||
'repoquery',
|
||||
'--list',
|
||||
'tdnf-repoquery-{}'.format(dep)
|
||||
])
|
||||
assert(ret['retval'] == 0)
|
||||
|
|
@ -11,6 +11,10 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TDNF_ID_DEPENDS "tdnf:depends"
|
||||
#define TDNF_ID_REQUIRES_PRE "tdnf:requires-pre"
|
||||
|
||||
typedef struct _SolvSack
|
||||
{
|
||||
Pool* pPool;
|
||||
|
@ -44,6 +48,8 @@ typedef struct _SOLV_REPO_INFO_INTERNAL_
|
|||
int nCookieSet;
|
||||
}SOLV_REPO_INFO_INTERNAL, *PSOLV_REPO_INFO_INTERNAL;
|
||||
|
||||
extern Id allDepKeyIds[];
|
||||
|
||||
// tdnfpackage.c
|
||||
uint32_t
|
||||
SolvGetPkgInfoFromId(
|
||||
|
@ -266,6 +272,35 @@ SolvGetNevraFromId(
|
|||
char **ppszEVR
|
||||
);
|
||||
|
||||
uint32_t
|
||||
SolvGetDependenciesFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
REPOQUERY_DEP_KEY depKey,
|
||||
char ***pppszDependencies);
|
||||
|
||||
uint32_t
|
||||
SolvGetFileListFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
char ***pppszFiles);
|
||||
|
||||
uint32_t
|
||||
SolvGetSourceFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
char **ppszName,
|
||||
char **ppszArch,
|
||||
char **ppszEVR
|
||||
);
|
||||
|
||||
uint32_t
|
||||
SolvGetChangeLogFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
PTDNF_PKG_CHANGELOG_ENTRY *ppEntries
|
||||
);
|
||||
|
||||
// tdnfpool.c
|
||||
uint32_t
|
||||
SolvCreateSack(
|
||||
|
@ -429,6 +464,25 @@ SolvGetUpdateAdvisories(
|
|||
Id dwPkgIdpkg,
|
||||
PSolvPackageList* ppPkgList);
|
||||
|
||||
uint32_t
|
||||
SolvApplyDepsFilter(
|
||||
PSolvQuery pQuery,
|
||||
char **ppszDeps,
|
||||
REPOQUERY_WHAT_KEY whatKey);
|
||||
|
||||
uint32_t
|
||||
SolvApplyExtrasFilter(
|
||||
PSolvQuery pQuery);
|
||||
|
||||
uint32_t
|
||||
SolvApplyDuplicatesFilter(
|
||||
PSolvQuery pQuery);
|
||||
|
||||
uint32_t
|
||||
SolvApplyFileProvidesFilter(
|
||||
PSolvQuery pQuery,
|
||||
char *pszFile);
|
||||
|
||||
// tdnfrepo.c
|
||||
uint32_t
|
||||
SolvReadYumRepo(
|
||||
|
@ -437,7 +491,8 @@ SolvReadYumRepo(
|
|||
const char *pszRepomd,
|
||||
const char *pszPrimary,
|
||||
const char *pszFilelists,
|
||||
const char *pszUpdateinfo
|
||||
const char *pszUpdateinfo,
|
||||
const char *pszOther
|
||||
);
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -1924,3 +1924,299 @@ error:
|
|||
TDNF_SAFE_FREE_MEMORY(pszEVR);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvGetDependenciesFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
REPOQUERY_DEP_KEY depKey,
|
||||
char ***pppszDependencies)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Solvable *pSolv = NULL;
|
||||
Queue queueDeps = {0};
|
||||
char **ppszDependencies = NULL;
|
||||
const char *pszDep = NULL;
|
||||
int nNumDeps, i, j;
|
||||
|
||||
if(!pSack || !pppszDependencies)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pSolv = pool_id2solvable(pSack->pPool, dwPkgId);
|
||||
if(!pSolv)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
if (depKey == REPOQUERY_DEP_KEY_DEPENDS)
|
||||
{
|
||||
Id allDepKeys[] = {
|
||||
SOLVABLE_REQUIRES,
|
||||
SOLVABLE_RECOMMENDS,
|
||||
SOLVABLE_SUGGESTS,
|
||||
SOLVABLE_SUPPLEMENTS,
|
||||
SOLVABLE_ENHANCES
|
||||
};
|
||||
queue_init(&queueDeps);
|
||||
for (i = 0; i < (int)ARRAY_SIZE(allDepKeys); i++)
|
||||
{
|
||||
Queue queueTmp = {0};
|
||||
solvable_lookup_deparray(pSolv, allDepKeys[i], &queueTmp, -1);
|
||||
|
||||
for (j = 0; j < queueTmp.count; j++)
|
||||
{
|
||||
queue_pushunique(&queueDeps, queueTmp.elements[j]);
|
||||
}
|
||||
queue_free(&queueTmp);
|
||||
}
|
||||
}
|
||||
else if (depKey == REPOQUERY_DEP_KEY_REQUIRES_PRE)
|
||||
{
|
||||
solvable_lookup_deparray(pSolv, SOLVABLE_REQUIRES, &queueDeps, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Id allDepKeyIds[] = {
|
||||
ID_NULL,
|
||||
SOLVABLE_PROVIDES,
|
||||
SOLVABLE_OBSOLETES,
|
||||
SOLVABLE_CONFLICTS,
|
||||
SOLVABLE_REQUIRES,
|
||||
SOLVABLE_RECOMMENDS,
|
||||
SOLVABLE_SUGGESTS,
|
||||
SOLVABLE_SUPPLEMENTS,
|
||||
SOLVABLE_ENHANCES
|
||||
};
|
||||
solvable_lookup_deparray(pSolv, allDepKeyIds[depKey], &queueDeps, -1);
|
||||
}
|
||||
nNumDeps = queueDeps.count;
|
||||
|
||||
dwError = TDNFAllocateMemory(nNumDeps + 1, sizeof(char *), (void**)&ppszDependencies);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
for (i = 0; i < nNumDeps; i++)
|
||||
{
|
||||
pszDep = pool_id2str(pSack->pPool, queueDeps.elements[i]);
|
||||
dwError = TDNFAllocateString(pszDep, &ppszDependencies[i]);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
*pppszDependencies = ppszDependencies;
|
||||
|
||||
cleanup:
|
||||
queue_free(&queueDeps);
|
||||
return dwError;
|
||||
error:
|
||||
TDNFFreeStringArray(ppszDependencies);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvGetFileListFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
char ***pppszFiles)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Solvable *pSolv = NULL;
|
||||
Dataiterator di;
|
||||
int i = 0, nCount = 0;
|
||||
char **ppszFiles = NULL;
|
||||
|
||||
if(!pSack || !pppszFiles)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pSolv = pool_id2solvable(pSack->pPool, dwPkgId);
|
||||
if(!pSolv)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dataiterator_init(&di, pSack->pPool, pSolv->repo, dwPkgId, SOLVABLE_FILELIST, NULL,
|
||||
SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
|
||||
while (dataiterator_step(&di)) {
|
||||
nCount++;
|
||||
}
|
||||
dataiterator_free(&di);
|
||||
|
||||
dwError = TDNFAllocateMemory(nCount + 1, sizeof(char *), (void**)&ppszFiles);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
dataiterator_init(&di, pSack->pPool, pSolv->repo, dwPkgId, SOLVABLE_FILELIST, NULL,
|
||||
SEARCH_FILES | SEARCH_COMPLETE_FILELIST);
|
||||
while (dataiterator_step(&di)) {
|
||||
dwError = TDNFAllocateString(di.kv.str, &ppszFiles[i++]);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
dataiterator_free(&di);
|
||||
|
||||
*pppszFiles = ppszFiles;
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
TDNFFreeStringArray(ppszFiles);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvGetSourceFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
char **ppszName,
|
||||
char **ppszArch,
|
||||
char **ppszEVR
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
const char* pszTmp = NULL;
|
||||
Solvable *pSolv = NULL;
|
||||
char *pszName = NULL;
|
||||
char *pszArch = NULL;
|
||||
char *pszEVR = NULL;
|
||||
|
||||
if(!pSack || !ppszName || !ppszArch || !ppszEVR)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pSolv = pool_id2solvable(pSack->pPool, dwPkgId);
|
||||
if(!pSolv)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
pszTmp = solvable_lookup_str(pSolv, SOLVABLE_SOURCENAME);
|
||||
if(!pszTmp)
|
||||
{
|
||||
/* if the name is the same we get NULL */
|
||||
pszTmp = solvable_lookup_str(pSolv, SOLVABLE_NAME);
|
||||
}
|
||||
if(!pszTmp)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFAllocateString(pszTmp, &pszName);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
pszTmp = solvable_lookup_str(pSolv, SOLVABLE_SOURCEARCH);
|
||||
if(!pszTmp)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFAllocateString(pszTmp, &pszArch);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
pszTmp = solvable_lookup_str(pSolv, SOLVABLE_SOURCEEVR);
|
||||
if(!pszTmp)
|
||||
{
|
||||
/* if the evr is the same we get NULL */
|
||||
pszTmp = solvable_lookup_str(pSolv, SOLVABLE_EVR);
|
||||
}
|
||||
if(!pszTmp)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFAllocateString(pszTmp, &pszEVR);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
|
||||
*ppszName = pszName;
|
||||
*ppszArch = pszArch;
|
||||
*ppszEVR = pszEVR;
|
||||
cleanup:
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
*ppszName = NULL;
|
||||
*ppszArch = NULL;
|
||||
*ppszEVR = NULL;
|
||||
TDNF_SAFE_FREE_MEMORY(pszName);
|
||||
TDNF_SAFE_FREE_MEMORY(pszArch);
|
||||
TDNF_SAFE_FREE_MEMORY(pszEVR);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvGetChangeLogFromId(
|
||||
PSolvSack pSack,
|
||||
uint32_t dwPkgId,
|
||||
PTDNF_PKG_CHANGELOG_ENTRY *ppEntries
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Solvable *pSolv = NULL;
|
||||
Dataiterator di;
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntry = NULL;
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntryNext = NULL;
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntries = NULL;
|
||||
|
||||
if(!pSack || !ppEntries)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pSolv = pool_id2solvable(pSack->pPool, dwPkgId);
|
||||
if(!pSolv)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
dataiterator_init(&di, pSack->pPool, pSolv->repo, dwPkgId,
|
||||
SOLVABLE_CHANGELOG_AUTHOR, NULL, 0);
|
||||
dataiterator_prepend_keyname(&di, SOLVABLE_CHANGELOG);
|
||||
while (dataiterator_step(&di)) {
|
||||
dataiterator_setpos_parent(&di);
|
||||
|
||||
pEntryNext = pEntry;
|
||||
dwError = TDNFAllocateMemory(sizeof(TDNF_PKG_CHANGELOG_ENTRY), 1, (void **)&pEntry);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
if (pEntries == NULL)
|
||||
{
|
||||
pEntries = pEntry;
|
||||
}
|
||||
pEntry->pNext = pEntryNext;
|
||||
|
||||
pEntry->timeTime =
|
||||
(time_t)pool_lookup_num(pSack->pPool, SOLVID_POS,
|
||||
SOLVABLE_CHANGELOG_TIME, 0);
|
||||
dwError = TDNFAllocateString(
|
||||
pool_lookup_str(pSack->pPool, SOLVID_POS, SOLVABLE_CHANGELOG_AUTHOR),
|
||||
&pEntry->pszAuthor);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
dwError = TDNFAllocateString(
|
||||
pool_lookup_str(pSack->pPool, SOLVID_POS, SOLVABLE_CHANGELOG_TEXT),
|
||||
&pEntry->pszText);
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
dataiterator_free(&di);
|
||||
|
||||
*ppEntries = pEntry;
|
||||
|
||||
cleanup:
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
for (pEntry = pEntries; pEntry; pEntry = pEntryNext)
|
||||
{
|
||||
pEntryNext = pEntry->pNext;
|
||||
TDNFFreeChangeLogEntry(pEntry);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
298
solv/tdnfquery.c
298
solv/tdnfquery.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2018 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -177,6 +177,7 @@ SolvCreateQuery(
|
|||
queue_init(&pQuery->queueJob);
|
||||
queue_init(&pQuery->queueRepoFilter);
|
||||
queue_init(&pQuery->queueResult);
|
||||
|
||||
*ppQuery = pQuery;
|
||||
|
||||
cleanup:
|
||||
|
@ -724,7 +725,6 @@ SolvApplyListQuery(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
queue_free(&queueTmp);
|
||||
return dwError;
|
||||
|
@ -1114,3 +1114,297 @@ cleanup:
|
|||
error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvApplyDepsFilter(
|
||||
PSolvQuery pQuery,
|
||||
char **ppszDeps,
|
||||
REPOQUERY_WHAT_KEY whatKey)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Queue queueDeps = {0};
|
||||
Queue queueFiltered = {0};
|
||||
int i, j;
|
||||
Id idDep;
|
||||
|
||||
if(!pQuery || !pQuery->pSack || !ppszDeps)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
/* convert string dep array to id queue */
|
||||
queue_init(&queueDeps);
|
||||
for(i = 0; ppszDeps[i] != NULL; i++)
|
||||
{
|
||||
idDep = pool_str2id(pQuery->pSack->pPool, ppszDeps[i], 0);
|
||||
/* if it's not found, nothing can depend on it */
|
||||
if (idDep)
|
||||
{
|
||||
queue_push(&queueDeps, idDep);
|
||||
}
|
||||
}
|
||||
|
||||
queue_init(&queueFiltered);
|
||||
for (j = 0; j < pQuery->queueResult.count; j++)
|
||||
{
|
||||
Id idPkg = pQuery->queueResult.elements[j];
|
||||
Solvable *pSolvable = pool_id2solvable(pQuery->pSack->pPool, idPkg);
|
||||
|
||||
if(!pSolvable)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
for (i = 0; i < queueDeps.count; i++)
|
||||
{
|
||||
idDep = queueDeps.elements[i];
|
||||
|
||||
if (whatKey != REPOQUERY_WHAT_KEY_DEPENDS)
|
||||
{
|
||||
Id allDepKeyIds[] = {
|
||||
SOLVABLE_PROVIDES,
|
||||
SOLVABLE_OBSOLETES,
|
||||
SOLVABLE_CONFLICTS,
|
||||
SOLVABLE_REQUIRES,
|
||||
SOLVABLE_RECOMMENDS,
|
||||
SOLVABLE_SUGGESTS,
|
||||
SOLVABLE_SUPPLEMENTS,
|
||||
SOLVABLE_ENHANCES
|
||||
};
|
||||
/* single dependency type */
|
||||
if (solvable_matchesdep(pSolvable, allDepKeyIds[whatKey], idDep, 0))
|
||||
{
|
||||
queue_push(&queueFiltered, idPkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t k;
|
||||
Id allDepKeys[] = {
|
||||
SOLVABLE_REQUIRES,
|
||||
SOLVABLE_RECOMMENDS,
|
||||
SOLVABLE_SUGGESTS,
|
||||
SOLVABLE_SUPPLEMENTS,
|
||||
SOLVABLE_ENHANCES
|
||||
};
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(allDepKeys); k++)
|
||||
{
|
||||
if (solvable_matchesdep(pSolvable, allDepKeys[k], idDep, 0))
|
||||
{
|
||||
queue_push(&queueFiltered, idPkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k < ARRAY_SIZE(allDepKeys))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queue_free(&pQuery->queueResult);
|
||||
pQuery->queueResult = queueFiltered;
|
||||
|
||||
cleanup:
|
||||
queue_free(&queueDeps);
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
queue_free(&queueFiltered);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvApplyExtrasFilter(
|
||||
PSolvQuery pQuery)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Pool *pPool;
|
||||
Queue queueExtras = {0};
|
||||
int i, j;
|
||||
|
||||
if(!pQuery)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pPool = pQuery->pSack->pPool;
|
||||
|
||||
queue_init(&queueExtras);
|
||||
|
||||
/* Outer loop iterates over all installed solvables,
|
||||
inner loop over all solvables that are *not* installed.
|
||||
If we don't find a match, it's an extra package */
|
||||
for (i = 0; i < pQuery->queueResult.count; i++)
|
||||
{
|
||||
Id idPkg = pQuery->queueResult.elements[i];
|
||||
Solvable *pSolvable = pool_id2solvable(pPool, idPkg);
|
||||
|
||||
if(!pSolvable)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
if (pSolvable->repo == pPool->installed)
|
||||
{
|
||||
int nFound = 0;
|
||||
for (j = 0; j < pQuery->queueResult.count; j++)
|
||||
{
|
||||
if (i != j)
|
||||
{
|
||||
Id idPkg2 = pQuery->queueResult.elements[j];
|
||||
Solvable *pSolvable2 = pool_id2solvable(pPool, idPkg2);
|
||||
|
||||
if(!pSolvable2)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
if (pSolvable2->repo == pPool->installed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pSolvable2->name == pSolvable->name &&
|
||||
pSolvable2->arch == pSolvable->arch &&
|
||||
pSolvable2->evr == pSolvable->evr)
|
||||
{
|
||||
nFound = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!nFound)
|
||||
{
|
||||
queue_push(&queueExtras, idPkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
queue_free(&pQuery->queueResult);
|
||||
pQuery->queueResult = queueExtras;
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
queue_free(&queueExtras);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvApplyDuplicatesFilter(
|
||||
PSolvQuery pQuery)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Pool *pPool;
|
||||
Queue queueDuplicates = {0};
|
||||
int i, j;
|
||||
|
||||
if(!pQuery)
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pPool = pQuery->pSack->pPool;
|
||||
|
||||
queue_init(&queueDuplicates);
|
||||
|
||||
for (i = 0; i < pQuery->queueResult.count; i++)
|
||||
{
|
||||
Id idPkg = pQuery->queueResult.elements[i];
|
||||
Solvable *pSolvable = pool_id2solvable(pPool, idPkg);
|
||||
|
||||
if(!pSolvable)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
|
||||
if (pSolvable->repo == pPool->installed)
|
||||
{
|
||||
int nFound = 0;
|
||||
/* no need to compare b with a if we already compared b with a,
|
||||
so we can start with j = i + 1 */
|
||||
for (j = i + 1; j < pQuery->queueResult.count; j++)
|
||||
{
|
||||
Id idPkg2 = pQuery->queueResult.elements[j];
|
||||
Solvable *pSolvable2 = pool_id2solvable(pPool, idPkg2);
|
||||
|
||||
if(!pSolvable2)
|
||||
{
|
||||
dwError = ERROR_TDNF_NO_DATA;
|
||||
BAIL_ON_TDNF_ERROR(dwError);
|
||||
}
|
||||
if (pSolvable2->repo != pPool->installed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pSolvable2->name == pSolvable->name &&
|
||||
pSolvable2->arch == pSolvable->arch)
|
||||
{
|
||||
nFound = 1;
|
||||
}
|
||||
}
|
||||
if (nFound)
|
||||
{
|
||||
queue_push(&queueDuplicates, idPkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
queue_free(&pQuery->queueResult);
|
||||
pQuery->queueResult = queueDuplicates;
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
queue_free(&queueDuplicates);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvApplyFileProvidesFilter(
|
||||
PSolvQuery pQuery,
|
||||
char *pszFile)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
Pool *pool;
|
||||
Queue queueFiltered = {0};
|
||||
Dataiterator di;
|
||||
int i;
|
||||
|
||||
if(!pQuery || IsNullOrEmptyString(pszFile))
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
pool = pQuery->pSack->pPool;
|
||||
|
||||
queue_init(&queueFiltered);
|
||||
|
||||
for (i = 0; i < pQuery->queueResult.count; i++)
|
||||
{
|
||||
Id idPkg = pQuery->queueResult.elements[i];
|
||||
|
||||
dataiterator_init(&di, pool, NULL, idPkg, SOLVABLE_FILELIST, pszFile,
|
||||
SEARCH_FILES | SEARCH_STRING);
|
||||
/* using 'if' instead of 'while' because one match is enough */
|
||||
if (dataiterator_step(&di)) {
|
||||
queue_push(&queueFiltered, idPkg);
|
||||
}
|
||||
dataiterator_free(&di);
|
||||
}
|
||||
queue_free(&pQuery->queueResult);
|
||||
pQuery->queueResult = queueFiltered;
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
queue_free(&queueFiltered);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2015 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -150,6 +150,43 @@ error:
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvLoadRepomdOther(
|
||||
Repo* pRepo,
|
||||
const char* pszOther
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
FILE *fp = NULL;
|
||||
if( !pRepo || IsNullOrEmptyString(pszOther))
|
||||
{
|
||||
dwError = ERROR_TDNF_INVALID_PARAMETER;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
fp = solv_xfopen(pszOther, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
dwError = ERROR_TDNF_SOLV_IO;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
if (repo_add_rpmmd(pRepo, fp, 0, REPO_EXTEND_SOLVABLES))
|
||||
{
|
||||
dwError = ERROR_TDNF_SOLV_IO;
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
cleanup:
|
||||
if(fp != NULL)
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
goto cleanup;
|
||||
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SolvReadYumRepo(
|
||||
Repo *pRepo,
|
||||
|
@ -157,7 +194,8 @@ SolvReadYumRepo(
|
|||
const char *pszRepomd,
|
||||
const char *pszPrimary,
|
||||
const char *pszFilelists,
|
||||
const char *pszUpdateinfo
|
||||
const char *pszUpdateinfo,
|
||||
const char *pszOther
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
|
@ -167,7 +205,6 @@ SolvReadYumRepo(
|
|||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
|
||||
dwError = SolvLoadRepomd(pRepo, pszRepomd);
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
|
||||
|
@ -187,6 +224,12 @@ SolvReadYumRepo(
|
|||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
if(pszOther)
|
||||
{
|
||||
dwError = SolvLoadRepomdOther(pRepo, pszOther);
|
||||
BAIL_ON_TDNF_LIBSOLV_ERROR(dwError);
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
|
|
|
@ -67,4 +67,5 @@
|
|||
{ERROR_TDNF_CLI_SETOPT_NO_EQUALS, "ERROR_TDNF_CLI_SETOPT_NO_EQUALS", "Missing equal sign in setopt argument. setopt requires an argument of the form key=value."}, \
|
||||
{ERROR_TDNF_CLI_NO_SUCH_CMD, "ERROR_TDNF_CLI_NO_SUCH_CMD", "Please check your command"}, \
|
||||
{ERROR_TDNF_CLI_DOWNLOADDIR_REQUIRES_DOWNLOADONLY, "ERROR_TDNF_CLI_DOWNLOADDIR_REQUIRES_DOWNLOADONLY", "--downloaddir requires --downloadonly"}, \
|
||||
{ERROR_TDNF_CLI_ONE_DEP_ONLY, "ERROR_TDNF_CLI_ONE_DEP_ONLY", "only one dependency allowed"}, \
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ add_library(${LIB_TDNF_CLI} SHARED
|
|||
parselistargs.c
|
||||
parserepolistargs.c
|
||||
parsereposyncargs.c
|
||||
parserepoqueryargs.c
|
||||
parseupdateinfo.c
|
||||
updateinfocmd.c
|
||||
)
|
||||
|
|
|
@ -485,6 +485,128 @@ error:
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFCliRepoQueryCommand(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
PTDNF_CMD_ARGS pCmdArgs
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
uint32_t dwCount = 0;
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs;
|
||||
PTDNF_PKG_INFO pPkgInfo = NULL;
|
||||
PTDNF_PKG_INFO pPkgInfos = NULL;
|
||||
int nCount = 0, i, j, k;
|
||||
char **ppszLines = NULL;
|
||||
|
||||
if(!pContext || !pContext->hTdnf || !pCmdArgs || !pContext->pFnRepoQuery)
|
||||
{
|
||||
dwError = ERROR_TDNF_CLI_INVALID_ARGUMENT;
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFCliParseRepoQueryArgs(pCmdArgs, &pRepoqueryArgs);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
|
||||
dwError = pContext->pFnRepoQuery(pContext, pRepoqueryArgs, &pPkgInfos, &dwCount);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
for (i = 0; i < (int)dwCount; i++)
|
||||
{
|
||||
pPkgInfo = &pPkgInfos[i];
|
||||
|
||||
if (pPkgInfo->ppszDependencies)
|
||||
{
|
||||
for (j = 0; pPkgInfo->ppszDependencies[j]; j++);
|
||||
nCount += j;
|
||||
}
|
||||
else if (pPkgInfo->ppszFileList)
|
||||
{
|
||||
for (j = 0; pPkgInfo->ppszFileList[j]; j++);
|
||||
nCount += j;
|
||||
}
|
||||
else if (pPkgInfo->pChangeLogEntries)
|
||||
{
|
||||
PTDNF_PKG_CHANGELOG_ENTRY pEntry;
|
||||
for (pEntry = pPkgInfo->pChangeLogEntries; pEntry; pEntry = pEntry->pNext)
|
||||
{
|
||||
char szTime[20] = {0};
|
||||
if (strftime(szTime, 20, "%a %b %d %Y", localtime(&pEntry->timeTime)))
|
||||
{
|
||||
pr_crit("%s %s\n%s\n",
|
||||
szTime,
|
||||
pEntry->pszAuthor,
|
||||
pEntry->pszText);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwError = ERROR_TDNF_CLI_INVALID_ARGUMENT;
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pPkgInfo->pszSourcePkg)
|
||||
{
|
||||
pr_crit("%s\n", pPkgInfo->pszSourcePkg);
|
||||
}
|
||||
else
|
||||
{
|
||||
pr_crit("%s-%s-%s.%s\n",
|
||||
pPkgInfo->pszName,
|
||||
pPkgInfo->pszVersion,
|
||||
pPkgInfo->pszRelease,
|
||||
pPkgInfo->pszArch);
|
||||
}
|
||||
}
|
||||
|
||||
if (nCount > 0)
|
||||
{
|
||||
dwError = TDNFAllocateMemory(nCount + 1, sizeof(char *), (void**)&ppszLines);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
for (k = 0, i = 0; i < (int)dwCount; i++)
|
||||
{
|
||||
pPkgInfo = &pPkgInfos[i];
|
||||
|
||||
if (pPkgInfo->ppszDependencies)
|
||||
{
|
||||
for (j = 0; pPkgInfo->ppszDependencies[j]; j++)
|
||||
{
|
||||
ppszLines[k++] = pPkgInfo->ppszDependencies[j];
|
||||
}
|
||||
}
|
||||
else if (pPkgInfo->ppszFileList)
|
||||
{
|
||||
for (j = 0; pPkgInfo->ppszFileList[j]; j++)
|
||||
{
|
||||
ppszLines[k++] = pPkgInfo->ppszFileList[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dwError = TDNFStringArraySort(ppszLines);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
|
||||
for (j = 0; ppszLines[j]; j++)
|
||||
{
|
||||
if (j == 0 || strcmp(ppszLines[j], ppszLines[j-1]))
|
||||
{
|
||||
pr_crit("%s\n", ppszLines[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if(pPkgInfos)
|
||||
{
|
||||
TDNFFreePackageInfoArray(pPkgInfos, dwCount);
|
||||
}
|
||||
TDNF_CLI_SAFE_FREE_MEMORY(ppszLines);
|
||||
TDNFCliFreeRepoQueryArgs(pRepoqueryArgs);
|
||||
return dwError;
|
||||
|
||||
error:
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFCliCheckUpdateCommand(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
|
|
|
@ -61,6 +61,33 @@ TDNFCliShowHelp(
|
|||
pr_crit(" [--downloadonly]\n");
|
||||
pr_crit(" [--downloaddir=<directory>]\n");
|
||||
pr_crit("\n");
|
||||
pr_crit("repoquery select options:\n");
|
||||
pr_crit(" [--available\n");
|
||||
pr_crit(" [--duplicates\n");
|
||||
pr_crit(" [--extras\n");
|
||||
pr_crit(" [--file <file>\n");
|
||||
pr_crit(" [--installed\n");
|
||||
pr_crit(" [--whatdepends <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatrequires <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatenhances <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatobsoletes <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatprovides <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatrecommends <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatrequires <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatsuggests <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit(" [--whatsupplements <capability1>[,<capability2>[..]]]\n");
|
||||
pr_crit("repoquery query options:\n");
|
||||
pr_crit(" [--depends\n");
|
||||
pr_crit(" [--enhances\n");
|
||||
pr_crit(" [--list\n");
|
||||
pr_crit(" [--obsoletes\n");
|
||||
pr_crit(" [--provides\n");
|
||||
pr_crit(" [--recommends\n");
|
||||
pr_crit(" [--requires\n");
|
||||
pr_crit(" [--requires-pre\n");
|
||||
pr_crit(" [--suggests\n");
|
||||
pr_crit(" [--supplements\n");
|
||||
pr_crit("\n");
|
||||
pr_crit("reposync options:\n");
|
||||
pr_crit(" [--arch=<arch> [--arch=<arch> [..]]\n");
|
||||
pr_crit(" [--delete]\n");
|
||||
|
@ -92,6 +119,7 @@ TDNFCliShowHelp(
|
|||
pr_crit("remove Remove a package or packages from your system\n");
|
||||
pr_crit("reinstall reinstall a package\n");
|
||||
pr_crit("repolist Display the configured software repositories\n");
|
||||
pr_crit("repoquery Query repositories\n");
|
||||
pr_crit("reposync Download all packages from one or more repositories to a directory\n");
|
||||
pr_crit("search Search package details for the given string\n");
|
||||
pr_crit("update Upgrade a package or packages on your system (same as 'upgrade')\n");
|
||||
|
|
|
@ -37,7 +37,36 @@ static SetOptArgs OptValTable[] = {
|
|||
{CMDOPT_KEYVALUE, "skipconflicts;skipobsoletes;skipsignature;skipdigest;"
|
||||
"noplugins;reboot-required;security;"
|
||||
"delete;download-metadata;gpgcheck;newest-only;norepopath;source;urls",
|
||||
"1"}
|
||||
"1"},
|
||||
{CMDOPT_KEYVALUE, "available", "1"},
|
||||
{CMDOPT_KEYVALUE, "installed", "1"},
|
||||
{CMDOPT_KEYVALUE, "extras", "1"},
|
||||
{CMDOPT_KEYVALUE, "changelogs", "1"},
|
||||
{CMDOPT_KEYVALUE, "duplicates", "1"},
|
||||
/* "depends" must be before "whatdepends",
|
||||
same for the others with partial string matches */
|
||||
{CMDOPT_KEYVALUE, "depends", "1"},
|
||||
{CMDOPT_KEYVALUE, "provides", "1"},
|
||||
{CMDOPT_KEYVALUE, "obsoletes", "1"},
|
||||
{CMDOPT_KEYVALUE, "conflicts", "1"},
|
||||
{CMDOPT_KEYVALUE, "requires", "1"},
|
||||
{CMDOPT_KEYVALUE, "recommends", "1"},
|
||||
{CMDOPT_KEYVALUE, "suggests", "1"},
|
||||
{CMDOPT_KEYVALUE, "supplements", "1"},
|
||||
{CMDOPT_KEYVALUE, "enhances", "1"},
|
||||
{CMDOPT_KEYVALUE, "requires-pre", "1"},
|
||||
{CMDOPT_KEYVALUE, "list", "1"},
|
||||
{CMDOPT_KEYVALUE, "upgrades", "1"},
|
||||
{CMDOPT_KEYVALUE, "file", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatdepends", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatprovides", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatobsoletes", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatconflicts", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatrequires", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatrecommends", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatsuggests", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatsupplements", NULL},
|
||||
{CMDOPT_KEYVALUE, "whatenhances", NULL},
|
||||
};
|
||||
|
||||
static TDNF_CMD_ARGS _opt = {0};
|
||||
|
@ -94,6 +123,36 @@ static struct option pstOptions[] =
|
|||
{"download-path", required_argument, 0, 0},
|
||||
{"source", no_argument, 0, 0},
|
||||
{"urls", no_argument, 0, 0},
|
||||
// repoquery option
|
||||
// repoquery select options
|
||||
{"file", required_argument, 0, 0},
|
||||
{"whatdepends", required_argument, 0, 0},
|
||||
{"whatprovides", required_argument, 0, 0},
|
||||
{"whatobsoletes", required_argument, 0, 0},
|
||||
{"whatconflicts", required_argument, 0, 0},
|
||||
{"whatrequires", required_argument, 0, 0},
|
||||
{"whatrecommends",required_argument, 0, 0},
|
||||
{"whatsuggests", required_argument, 0, 0},
|
||||
{"whatsupplements", required_argument, 0, 0},
|
||||
{"whatenhances", required_argument, 0, 0},
|
||||
// repoquery query options
|
||||
{"available", no_argument, 0, 0},
|
||||
{"changelogs", no_argument, 0, 0},
|
||||
{"installed", no_argument, 0, 0},
|
||||
{"extras", no_argument, 0, 0},
|
||||
{"duplicates", no_argument, 0, 0},
|
||||
{"depends", no_argument, 0, 0},
|
||||
{"provides", no_argument, 0, 0},
|
||||
{"obsoletes", no_argument, 0, 0},
|
||||
{"conflicts", no_argument, 0, 0},
|
||||
{"requires", no_argument, 0, 0},
|
||||
{"recommends", no_argument, 0, 0},
|
||||
{"suggests", no_argument, 0, 0},
|
||||
{"supplements", no_argument, 0, 0},
|
||||
{"enhances", no_argument, 0, 0},
|
||||
{"requires-pre", no_argument, 0, 0},
|
||||
{"list", no_argument, 0, 0},
|
||||
{"upgrades", no_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) 2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU Lesser General Public License v2.1 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
* of the License are located in the COPYING file of this distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module : parserepoqueryargs.c
|
||||
*
|
||||
* Abstract :
|
||||
*
|
||||
* tdnf
|
||||
*
|
||||
* command line tools
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
char *depKeys[] = {
|
||||
"provides",
|
||||
"obsoletes",
|
||||
"conflicts",
|
||||
"requires",
|
||||
"recommends",
|
||||
"suggests",
|
||||
"supplements",
|
||||
"enhances",
|
||||
"depends",
|
||||
"requires-pre"
|
||||
};
|
||||
|
||||
char *whatKeys[REPOQUERY_WHAT_KEY_COUNT] = {
|
||||
"whatprovides",
|
||||
"whatobsoletes",
|
||||
"whatconflicts",
|
||||
"whatrequires",
|
||||
"whatrecommends",
|
||||
"whatsuggests",
|
||||
"whatsupplements",
|
||||
"whatenhances",
|
||||
"whatdepends"
|
||||
};
|
||||
|
||||
uint32_t
|
||||
TDNFCliParseRepoQueryArgs(
|
||||
PTDNF_CMD_ARGS pArgs,
|
||||
PTDNF_REPOQUERY_ARGS* ppRepoqueryArgs
|
||||
)
|
||||
{
|
||||
uint32_t dwError = 0;
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs = NULL;
|
||||
PTDNF_CMD_OPT pSetOpt = NULL;
|
||||
|
||||
if (!pArgs || !ppRepoqueryArgs)
|
||||
{
|
||||
dwError = ERROR_TDNF_CLI_INVALID_ARGUMENT;
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
|
||||
dwError = TDNFAllocateMemory(
|
||||
1,
|
||||
sizeof(TDNF_REPOQUERY_ARGS),
|
||||
(void**) &pRepoqueryArgs);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
|
||||
dwError = TDNFAllocateMemory(
|
||||
REPOQUERY_WHAT_KEY_COUNT,
|
||||
sizeof(char **),
|
||||
(void **) &pRepoqueryArgs->pppszWhatKeys);
|
||||
|
||||
for (pSetOpt = pArgs->pSetOpt;
|
||||
pSetOpt;
|
||||
pSetOpt = pSetOpt->pNext)
|
||||
{
|
||||
if(pSetOpt->nType == CMDOPT_KEYVALUE)
|
||||
{
|
||||
if (strcasecmp(pSetOpt->pszOptName, "file") == 0)
|
||||
{
|
||||
dwError = TDNFAllocateString(pSetOpt->pszOptValue,
|
||||
&pRepoqueryArgs->pszFile);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "changelogs") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nChangeLogs = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "available") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nAvailable = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "installed") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nInstalled = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "extras") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nExtras = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "duplicates") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nDuplicates = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "list") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nList = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "source") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nSource = 1;
|
||||
}
|
||||
else if (strcasecmp(pSetOpt->pszOptName, "upgrades") == 0)
|
||||
{
|
||||
pRepoqueryArgs->nUpgrades = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
REPOQUERY_DEP_KEY depKey;
|
||||
|
||||
for (depKey = 0; depKey < REPOQUERY_DEP_KEY_COUNT - 1; depKey++)
|
||||
{
|
||||
if (strcasecmp(pSetOpt->pszOptName, depKeys[depKey]) == 0)
|
||||
{
|
||||
if (pRepoqueryArgs->depKey == 0)
|
||||
{
|
||||
pRepoqueryArgs->depKey = depKey + 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwError = ERROR_TDNF_CLI_ONE_DEP_ONLY;
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (depKey == REPOQUERY_DEP_KEY_COUNT - 1) /* not found in loop above */
|
||||
{
|
||||
REPOQUERY_WHAT_KEY whatKey;
|
||||
|
||||
for (whatKey = 0; whatKey < REPOQUERY_WHAT_KEY_COUNT; whatKey++)
|
||||
{
|
||||
if (strcasecmp(pSetOpt->pszOptName, whatKeys[whatKey]) == 0)
|
||||
{
|
||||
dwError = TDNFSplitStringToArray(pSetOpt->pszOptValue,
|
||||
",",
|
||||
&pRepoqueryArgs->pppszWhatKeys[whatKey]);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* if (i == REPOQUERY_WHAT_KEY_COUNT) */
|
||||
} /* if (strcasecmp(pSetOpt->pszOptName, ... */
|
||||
} /* if(pSetOpt->nType == CMDOPT_KEYVALUE) */
|
||||
} /* for (pSetOpt ... */
|
||||
|
||||
if(pArgs->nCmdCount > 2)
|
||||
{
|
||||
dwError = ERROR_TDNF_CLI_INVALID_ARGUMENT;
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
|
||||
if(pArgs->nCmdCount > 1)
|
||||
{
|
||||
dwError = TDNFAllocateString(pArgs->ppszCmds[1],
|
||||
&pRepoqueryArgs->pszSpec);
|
||||
BAIL_ON_CLI_ERROR(dwError);
|
||||
}
|
||||
|
||||
*ppRepoqueryArgs = pRepoqueryArgs;
|
||||
cleanup:
|
||||
return dwError;
|
||||
error:
|
||||
TDNFCliFreeRepoQueryArgs(pRepoqueryArgs);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
void
|
||||
TDNFCliFreeRepoQueryArgs(
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs
|
||||
)
|
||||
{
|
||||
if(pRepoqueryArgs)
|
||||
{
|
||||
if (pRepoqueryArgs->pppszWhatKeys)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < REPOQUERY_WHAT_KEY_COUNT; i++)
|
||||
{
|
||||
TDNF_CLI_SAFE_FREE_STRINGARRAY(pRepoqueryArgs->pppszWhatKeys[i]);
|
||||
TDNFFreeMemory(pRepoqueryArgs->pppszWhatKeys[i]);
|
||||
}
|
||||
TDNFFreeMemory(pRepoqueryArgs->pppszWhatKeys);
|
||||
}
|
||||
TDNF_CLI_SAFE_FREE_MEMORY(pRepoqueryArgs->pszFile);
|
||||
TDNF_CLI_SAFE_FREE_MEMORY(pRepoqueryArgs->pszSpec);
|
||||
TDNF_CLI_SAFE_FREE_MEMORY(pRepoqueryArgs);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2018 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2015-2021 VMware, Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the GNU General Public License v2 (the "License");
|
||||
* you may not use this file except in compliance with the License. The terms
|
||||
|
@ -56,6 +56,7 @@ int main(int argc, char* argv[])
|
|||
{"remove", TDNFCliEraseCommand},
|
||||
{"repolist", TDNFCliRepoListCommand},
|
||||
{"reposync", TDNFCliRepoSyncCommand},
|
||||
{"repoquery", TDNFCliRepoQueryCommand},
|
||||
{"search", TDNFCliSearchCommand},
|
||||
{"update", TDNFCliUpgradeCommand},
|
||||
{"update-to", TDNFCliUpgradeCommand},
|
||||
|
@ -104,6 +105,7 @@ int main(int argc, char* argv[])
|
|||
_context.pFnProvides = TDNFCliInvokeProvides;
|
||||
_context.pFnRepoList = TDNFCliInvokeRepoList;
|
||||
_context.pFnRepoSync = TDNFCliInvokeRepoSync;
|
||||
_context.pFnRepoQuery = TDNFCliInvokeRepoQuery;
|
||||
|
||||
/*
|
||||
* Alter and resolve will address commands like
|
||||
|
@ -455,6 +457,17 @@ TDNFCliInvokeRepoSync(
|
|||
return TDNFRepoSync(pContext->hTdnf, pRepoSyncArgs);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFCliInvokeRepoQuery(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
PTDNF_REPOQUERY_ARGS pRepoQueryArgs,
|
||||
PTDNF_PKG_INFO *ppPkgInfos,
|
||||
uint32_t *pdwCount
|
||||
)
|
||||
{
|
||||
return TDNFRepoQuery(pContext->hTdnf, pRepoQueryArgs, ppPkgInfos, pdwCount);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TDNFCliInvokeResolve(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
|
|
|
@ -97,6 +97,14 @@ TDNFCliInvokeRepoSync(
|
|||
PTDNF_REPOSYNC_ARGS pReposyncArgs
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliInvokeRepoQuery(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
PTDNF_REPOQUERY_ARGS pRepoqueryArgs,
|
||||
PTDNF_PKG_INFO *ppPkgInfos,
|
||||
uint32_t *pdwCount
|
||||
);
|
||||
|
||||
uint32_t
|
||||
TDNFCliInvokeResolve(
|
||||
PTDNF_CLI_CONTEXT pContext,
|
||||
|
@ -314,6 +322,13 @@ TDNFCliParseRepoSyncArgs(
|
|||
PTDNF_REPOSYNC_ARGS* ppReposyncArgs
|
||||
);
|
||||
|
||||
//parserepoqueryargs.c
|
||||
uint32_t
|
||||
TDNFCliParseRepoQueryArgs(
|
||||
PTDNF_CMD_ARGS pCmdArgs,
|
||||
PTDNF_REPOQUERY_ARGS* ppRepoqueryArgs
|
||||
);
|
||||
|
||||
//parseupdateinfo.c
|
||||
uint32_t
|
||||
ParseMode(
|
||||
|
|
Loading…
Reference in New Issue