diff --git a/client/api.c b/client/api.c index e5cf543f..7444c686 100644 --- a/client/api.c +++ b/client/api.c @@ -812,7 +812,7 @@ TDNFAddCmdLinePackages( pTdnf, pszPkgName, basename(pszCopyOfPkgName), - "@cmdline", + CMDLINE_REPO_NAME, &pszRPMPath ); BAIL_ON_TDNF_ERROR(dwError); @@ -1063,7 +1063,7 @@ TDNFRepoSync( /* count enabled repos */ for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -1250,7 +1250,7 @@ TDNFRepoSync( marker file */ for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -1280,7 +1280,7 @@ TDNFRepoSync( { for (pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; diff --git a/client/defines.h b/client/defines.h index 8acdacbe..7cb16b8d 100644 --- a/client/defines.h +++ b/client/defines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2020 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 @@ -49,6 +49,8 @@ typedef enum } \ } while(0) +#define STR_IS_TRUE(s) ((s) && (!strcmp((s), "1") || !strcasecmp((s), "true"))) + //Misc #define TDNF_RPM_EXT ".rpm" #define TDNF_NAME "tdnf" @@ -136,7 +138,8 @@ typedef enum #define TDNF_REPO_DEFAULT_SSLVERIFY 1 #define TDNF_REPO_DEFAULT_RETRIES 10 #define TDNF_REPO_DEFAULT_PRIORITY 50 -#define TDNF_REPO_DEFAULT_METADATA_EXPIRE "172800" // 48 hours in seconds +#define TDNF_REPO_DEFAULT_METADATA_EXPIRE 172800 // 48 hours in seconds +#define TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR STRINGIFYX(TDNF_REPO_DEFAULT_METADATA_EXPIRE) // var names #define TDNF_VAR_RELEASEVER "$releasever" diff --git a/client/init.c b/client/init.c index 92316fce..71576144 100644 --- a/client/init.c +++ b/client/init.c @@ -254,7 +254,7 @@ TDNFRefreshSack( { /* skip the @cmdline repo - options do not apply, and it is initialized. */ - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; @@ -271,7 +271,7 @@ TDNFRefreshSack( for(pRepo = pTdnf->pRepos; pRepo; pRepo = pRepo->pNext) { - if ((strcmp(pRepo->pszName, "@cmdline") == 0) || + if ((strcmp(pRepo->pszName, CMDLINE_REPO_NAME) == 0) || (!pRepo->nEnabled)) { continue; diff --git a/client/prototypes.h b/client/prototypes.h index 2ede7952..ba1b07ac 100644 --- a/client/prototypes.h +++ b/client/prototypes.h @@ -753,6 +753,19 @@ TDNFCreateCmdLineRepo( PTDNF_REPO_DATA_INTERNAL* ppRepo ); +uint32_t +TDNFCreateRepoFromPath( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pzsId, + const char *pszPath + ); + +uint32_t +TDNFCreateRepo( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId + ); + uint32_t TDNFLoadRepoData( PTDNF pTdnf, diff --git a/client/repo.c b/client/repo.c index 65754e14..8465d11d 100644 --- a/client/repo.c +++ b/client/repo.c @@ -195,7 +195,7 @@ TDNFInitCmdLineRepo( (void**)&pSolvRepoInfo); BAIL_ON_TDNF_ERROR(dwError); - pRepo = repo_create(pPool, "@cmdline"); + pRepo = repo_create(pPool, CMDLINE_REPO_NAME); if (!pRepo) { dwError = ERROR_TDNF_INVALID_PARAMETER; diff --git a/client/repolist.c b/client/repolist.c index b19a24df..75eb70a3 100644 --- a/client/repolist.c +++ b/client/repolist.c @@ -34,12 +34,14 @@ TDNFLoadRepoData( PTDNF_REPO_DATA_INTERNAL pReposTemp = NULL; PTDNF_REPO_DATA_INTERNAL pRepos = NULL; PTDNF_CONF pConf = NULL; + PTDNF_CMD_OPT pSetOpt = NULL; DIR *pDir = NULL; struct dirent *pEnt = NULL; int nLen = 0; int nLenRepoExt = 0; + char **ppszUrlIdTuple = NULL; - if(!pTdnf || !pTdnf->pConf || !ppReposAll) + if(!pTdnf || !pTdnf->pConf || !pTdnf->pArgs || !ppReposAll) { dwError = ERROR_TDNF_INVALID_PARAMETER; BAIL_ON_TDNF_ERROR(dwError); @@ -49,6 +51,28 @@ TDNFLoadRepoData( dwError = TDNFCreateCmdLineRepo(&pReposAll); BAIL_ON_TDNF_ERROR(dwError); + for(pSetOpt = pTdnf->pArgs->pSetOpt; + pSetOpt; + pSetOpt = pSetOpt->pNext) + { + if(strcmp(pSetOpt->pszOptName, "repofrompath") == 0) + { + TDNFSplitStringToArray(pSetOpt->pszOptValue, ",", &ppszUrlIdTuple); + if ((ppszUrlIdTuple[0] == NULL) || ppszUrlIdTuple[1] == NULL) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + dwError = TDNFCreateRepoFromPath(&pReposAll, + ppszUrlIdTuple[0], + ppszUrlIdTuple[1]); + BAIL_ON_TDNF_ERROR(dwError); + + TDNF_SAFE_FREE_STRINGARRAY(ppszUrlIdTuple); + ppszUrlIdTuple = NULL; + } + } + pDir = opendir(pConf->pszRepoDir); if(pDir == NULL) { @@ -111,6 +135,7 @@ TDNFLoadRepoData( closedir(pDir); } TDNF_SAFE_FREE_MEMORY(pszRepoFilePath); + TDNF_SAFE_FREE_STRINGARRAY(ppszUrlIdTuple); return dwError; error: @@ -139,17 +164,120 @@ TDNFCreateCmdLineRepo( BAIL_ON_TDNF_ERROR(dwError); } + dwError = TDNFCreateRepo(&pRepo, CMDLINE_REPO_NAME); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFSafeAllocateString(CMDLINE_REPO_NAME, &pRepo->pszName); + BAIL_ON_TDNF_ERROR(dwError); + + *ppRepo = pRepo; +cleanup: + return dwError; +error: + if(pRepo) + { + TDNFFreeReposInternal(pRepo); + } + goto cleanup; +} + +uint32_t +TDNFCreateRepoFromPath( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId, + const char *pszPath + ) +{ + uint32_t dwError = 0; + PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + int nIsDir = 0; + int nDummy = 0; + + if(!ppRepo || !pszId || !pszPath) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + + dwError = TDNFCreateRepo(&pRepo, pszId); + BAIL_ON_TDNF_ERROR(dwError); + + /* we want it enabled, or there was no point in adding it */ + pRepo->nEnabled = 1; + + dwError = TDNFSafeAllocateString(pszId, &pRepo->pszName); + BAIL_ON_TDNF_ERROR(dwError); + + /* '/some/dir' => 'file:///some/dir */ + if (pszPath[0] == '/') + { + dwError = TDNFIsDir(pszPath, &nIsDir); + BAIL_ON_TDNF_ERROR(dwError); + + if (nIsDir) + { + dwError = TDNFAllocateStringPrintf(&pRepo->pszBaseUrl, "file://%s", pszPath); + BAIL_ON_TDNF_ERROR(dwError); + } + } + else + { + /* valid prefixes including file:// will not return an error */ + dwError = TDNFUriIsRemote(pszPath, &nDummy); + BAIL_ON_TDNF_ERROR(dwError); + + dwError = TDNFSafeAllocateString(pszPath, &pRepo->pszBaseUrl); + BAIL_ON_TDNF_ERROR(dwError); + } + *ppRepo = pRepo; +cleanup: + return dwError; +error: + if(ppRepo) + { + *ppRepo = NULL; + } + if(pRepo) + { + TDNFFreeReposInternal(pRepo); + } + goto cleanup; +} + +uint32_t +TDNFCreateRepo( + PTDNF_REPO_DATA_INTERNAL* ppRepo, + const char *pszId + ) +{ + uint32_t dwError = 0; + PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + + if(!ppRepo || !pszId) + { + dwError = ERROR_TDNF_INVALID_PARAMETER; + BAIL_ON_TDNF_ERROR(dwError); + } + dwError = TDNFAllocateMemory( 1, sizeof(TDNF_REPO_DATA_INTERNAL), (void**)&pRepo); BAIL_ON_TDNF_ERROR(dwError); - dwError = TDNFSafeAllocateString("@cmdline", &pRepo->pszName); + dwError = TDNFSafeAllocateString(pszId, &pRepo->pszId); BAIL_ON_TDNF_ERROR(dwError); - dwError = TDNFSafeAllocateString("@cmdline", &pRepo->pszId); - BAIL_ON_TDNF_ERROR(dwError); + pRepo->nEnabled = TDNF_REPO_DEFAULT_ENABLED; + pRepo->nSkipIfUnavailable = TDNF_REPO_DEFAULT_SKIP; + pRepo->nGPGCheck = TDNF_REPO_DEFAULT_GPGCHECK; + pRepo->nSSLVerify = TDNF_REPO_DEFAULT_SSLVERIFY; + pRepo->lMetadataExpire = TDNF_REPO_DEFAULT_METADATA_EXPIRE; + pRepo->nPriority = TDNF_REPO_DEFAULT_PRIORITY; + pRepo->nTimeout = TDNF_REPO_DEFAULT_TIMEOUT; + pRepo->nMinrate = TDNF_REPO_DEFAULT_MINRATE; + pRepo->nThrottle = TDNF_REPO_DEFAULT_THROTTLE; + pRepo->nRetries = TDNF_REPO_DEFAULT_RETRIES; *ppRepo = pRepo; cleanup: @@ -400,7 +528,7 @@ TDNFLoadReposFromFile( dwError = TDNFReadKeyValue( pSections, TDNF_REPO_KEY_METADATA_EXPIRE, - TDNF_REPO_DEFAULT_METADATA_EXPIRE, + TDNF_REPO_DEFAULT_METADATA_EXPIRE_STR, &pszMetadataExpire); BAIL_ON_TDNF_ERROR(dwError); @@ -451,6 +579,7 @@ TDNFRepoListFinalize( uint32_t dwError = 0; PTDNF_CMD_OPT pSetOpt = NULL; PTDNF_REPO_DATA_INTERNAL pRepo = NULL; + int nRepoidSeen = 0; if(!pTdnf || !pTdnf->pArgs || !pTdnf->pRepos) { @@ -472,8 +601,23 @@ TDNFRepoListFinalize( pSetOpt->nType == CMDOPT_ENABLEREPO, pSetOpt->pszOptValue); BAIL_ON_TDNF_ERROR(dwError); - } - pSetOpt = pSetOpt->pNext; + } + else if(strcmp(pSetOpt->pszOptName, "repoid") == 0) + { + if (!nRepoidSeen) + { + dwError = TDNFAlterRepoState( + pTdnf->pRepos, 0, "*"); + BAIL_ON_TDNF_ERROR(dwError); + nRepoidSeen = 1; + } + dwError = TDNFAlterRepoState( + pTdnf->pRepos, + 1, + pSetOpt->pszOptValue); + BAIL_ON_TDNF_ERROR(dwError); + } + pSetOpt = pSetOpt->pNext; } //Now that the overrides are applied, replace config vars diff --git a/common/defines.h b/common/defines.h index 494c1ecc..656566b8 100644 --- a/common/defines.h +++ b/common/defines.h @@ -20,6 +20,9 @@ #pragma once +#define STRINGIFYX(N) STRINGIFY(N) +#define STRINGIFY(N) #N + #define MAX_CONFIG_LINE_LENGTH 1024 #define TDNF_SAFE_FREE_PKGINFO(pPkgInfo) \ diff --git a/pytests/conftest.py b/pytests/conftest.py index 959c123f..64a5d25c 100644 --- a/pytests/conftest.py +++ b/pytests/conftest.py @@ -274,6 +274,26 @@ def _run(self, cmd, retvalonly=False, cwd=None): ret['retval'] = retval return ret + # helper to create directory tree without complains when it exists: + def makedirs(self, d): + try: + os.makedirs(d) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + def create_repoconf(self, filename, baseurl, name): + templ = """ +[{name}] +name=Test Repo +baseurl={baseurl} +enabled=1 +gpgcheck=0 +metadata_expire=86400 +ui_repoid_vars=basearch +""" + with open(filename, "w") as f: + f.write(templ.format(name=name, baseurl=baseurl)) @pytest.fixture(scope='session') def utils(): diff --git a/pytests/tests/test_installroot.py b/pytests/tests/test_installroot.py index 6b227347..fe5d04d8 100644 --- a/pytests/tests/test_installroot.py +++ b/pytests/tests/test_installroot.py @@ -28,17 +28,9 @@ def teardown_test(utils): shutil.rmtree(INSTALLROOT) pass -# helper to create directory tree without complains when it exists: -def makedirs(d): - try: - os.makedirs(d) - except OSError as e: - if e.errno != errno.EEXIST: - raise - def install_root(utils, no_reposd=False): - makedirs(INSTALLROOT) - makedirs(os.path.join(INSTALLROOT, 'etc/tdnf')) + utils.makedirs(INSTALLROOT) + utils.makedirs(os.path.join(INSTALLROOT, 'etc/tdnf')) conffile = os.path.join(utils.config['repo_path'], 'tdnf.conf') # remove special settings for repodir and cachedir @@ -50,10 +42,10 @@ def install_root(utils, no_reposd=False): fout.write(line) if not no_reposd: - makedirs(os.path.join(INSTALLROOT, 'etc/yum.repos.d')) + utils.makedirs(os.path.join(INSTALLROOT, 'etc/yum.repos.d')) repofile = os.path.join(utils.config['repo_path'], "yum.repos.d", REPOFILENAME) shutil.copyfile(repofile, os.path.join(INSTALLROOT, 'etc/yum.repos.d', REPOFILENAME)) - makedirs(os.path.join(INSTALLROOT, 'var/cache/tdnf')) + utils.makedirs(os.path.join(INSTALLROOT, 'var/cache/tdnf')) utils.run(['rpm', '--root', INSTALLROOT, '--initdb']) # local version of check_package with install root @@ -105,26 +97,13 @@ def test_makecache(utils): shutil.rmtree(INSTALLROOT) -def create_repoconf(filename, baseurl, name): - templ = """ -[{name}] -name=Test Repo -baseurl={baseurl} -enabled=1 -gpgcheck=0 -metadata_expire=86400 -ui_repoid_vars=basearch -""" - with open(filename, "w") as f: - f.write(templ.format(name=name, baseurl=baseurl)) - # --setopt=reposdir overrides any dir in install root def test_setopt_reposdir_with_installroot(utils): install_root(utils) - makedirs(REPODIR) - create_repoconf(os.path.join(REPODIR, REPOFILENAME), - "http://foo.bar.com/packages", - REPONAME) + utils.makedirs(REPODIR) + utils.create_repoconf(os.path.join(REPODIR, REPOFILENAME), + "http://foo.bar.com/packages", + REPONAME) ret = utils.run(['tdnf', '--installroot', INSTALLROOT, '--releasever=4.0', diff --git a/pytests/tests/test_repofrompath.py b/pytests/tests/test_repofrompath.py new file mode 100644 index 00000000..9b95ff41 --- /dev/null +++ b/pytests/tests/test_repofrompath.py @@ -0,0 +1,69 @@ +# +# 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 + +import os +import shutil +import pytest +import errno + +REPODIR='/root/repofrompath/yum.repos.d' +REPOFILENAME='repofrompath.repo' +REPONAME="repofrompath-test" +WORKDIR='/root/repofrompath/workdir' + +@pytest.fixture(scope='function', autouse=True) +def setup_test(utils): + yield + teardown_test(utils) + +def teardown_test(utils): + if os.path.isdir(REPODIR): + shutil.rmtree(REPODIR) + if os.path.isdir(WORKDIR): + shutil.rmtree(WORKDIR) + filename = os.path.join(utils.config['repo_path'], "yum.repos.d", REPOFILENAME) + if os.path.isfile(filename): + os.remove(filename) + +# reposync a repo and install from it +def test_repofrompath_created_repo(utils): + reponame = 'photon-test' + workdir = WORKDIR + utils.makedirs(workdir) + + ret = utils.run(['tdnf', '--repo={}'.format(reponame), + '--download-metadata', + 'reposync'], + cwd=workdir) + assert(ret['retval'] == 0) + synced_dir = os.path.join(workdir, reponame) + assert(os.path.isdir(synced_dir)) + assert(os.path.isdir(os.path.join(synced_dir, 'repodata'))) + assert(os.path.isfile(os.path.join(synced_dir, 'repodata', 'repomd.xml'))) + + baseurl = "file://{}".format(synced_dir) + + ret = utils.run(['tdnf', + '--repofrompath=synced-repo,{}'.format(synced_dir), + '--repo=synced-repo', + 'makecache'], + cwd=workdir) + assert(ret['retval'] == 0) + + pkgname = utils.config["mulversion_pkgname"] + utils.erase_package(pkgname) + ret = utils.run(['tdnf', + '-y', '--nogpgcheck', + '--repofrompath=synced-repo,{}'.format(synced_dir), + '--repo=synced-repo', + 'install', pkgname ], + cwd=workdir) + assert(ret['retval'] == 0) + assert(utils.check_package(pkgname) == True) + diff --git a/pytests/tests/test_repoid.py b/pytests/tests/test_repoid.py new file mode 100644 index 00000000..d35e407a --- /dev/null +++ b/pytests/tests/test_repoid.py @@ -0,0 +1,82 @@ +# +# 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 + +import os +import shutil +import pytest +import errno + +REPODIR='/root/repoid/yum.repos.d' +REPOFILENAME='repoid.repo' +REPONAME="repoid-test" +WORKDIR='/root/repoid/workdir' + +@pytest.fixture(scope='function', autouse=True) +def setup_test(utils): + yield + teardown_test(utils) + +def teardown_test(utils): + if os.path.isdir(REPODIR): + shutil.rmtree(REPODIR) + if os.path.isdir(WORKDIR): + shutil.rmtree(WORKDIR) + filename = os.path.join(utils.config['repo_path'], "yum.repos.d", REPOFILENAME) + if os.path.isfile(filename): + os.remove(filename) + +def test_repoid(utils): + utils.makedirs(REPODIR) + utils.create_repoconf(os.path.join(REPODIR, REPOFILENAME), + "http://foo.bar.com/packages", + REPONAME) + ret = utils.run(['tdnf', + '--setopt=reposdir={}'.format(REPODIR), + '--repoid={}'.format(REPONAME), + 'repolist']) + assert(ret['retval'] == 0) + assert(REPONAME in "\n".join(ret['stdout'])) + +# reposync a repo and install from it +def test_repoid_created_repo(utils): + reponame = 'photon-test' + workdir = WORKDIR + utils.makedirs(workdir) + + ret = utils.run(['tdnf', '--repo={}'.format(reponame), + '--download-metadata', + 'reposync'], + cwd=workdir) + assert(ret['retval'] == 0) + synced_dir = os.path.join(workdir, reponame) + assert(os.path.isdir(synced_dir)) + assert(os.path.isdir(os.path.join(synced_dir, 'repodata'))) + assert(os.path.isfile(os.path.join(synced_dir, 'repodata', 'repomd.xml'))) + + filename = os.path.join(utils.config['repo_path'], "yum.repos.d", REPOFILENAME) + baseurl = "file://{}".format(synced_dir) + + utils.create_repoconf(filename, baseurl, "synced-repo") + + ret = utils.run(['tdnf', + '--repo=synced-repo', + 'makecache'], + cwd=workdir) + assert(ret['retval'] == 0) + + pkgname = utils.config["mulversion_pkgname"] + utils.erase_package(pkgname) + ret = utils.run(['tdnf', + '-y', '--nogpgcheck', + '--repo=synced-repo', + 'install', pkgname ], + cwd=workdir) + assert(ret['retval'] == 0) + assert(utils.check_package(pkgname) == True) + diff --git a/pytests/tests/test_reposync.py b/pytests/tests/test_reposync.py index c362003c..90d8a57d 100644 --- a/pytests/tests/test_reposync.py +++ b/pytests/tests/test_reposync.py @@ -41,14 +41,6 @@ def teardown_test(utils): if os.path.isdir(os.path.join('/', TESTREPO)): shutil.rmtree(os.path.join('/', TESTREPO)) -# helper to create directory tree without complains when it exists: -def makedirs(d): - try: - os.makedirs(d) - except OSError as e: - if e.errno != errno.EEXIST: - raise - # helper to check a synced repo - # uses the local repository and compares the list of RPMs def check_synced_repo(utils, reponame, synced_dir): @@ -65,24 +57,11 @@ def check_synced_repo(utils, reponame, synced_dir): for rpm in local_rpms: assert(os.path.isfile(os.path.join(synced_dir, 'RPMS', ARCH, rpm))) -def create_repoconf(filename, baseurl, name): - templ = """ -[{name}] -name=Test Repo -baseurl={baseurl} -enabled=1 -gpgcheck=0 -metadata_expire=86400 -ui_repoid_vars=basearch -""" - with open(filename, "w") as f: - f.write(templ.format(name=name, baseurl=baseurl)) - # reposync with no options - sync to local directory def test_reposync(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), @@ -100,7 +79,7 @@ def test_reposync(utils): def test_reposync_download_path(utils): reponame = TESTREPO downloaddir = DOWNLOADDIR - makedirs(downloaddir) + utils.makedirs(downloaddir) assert(os.path.isdir(downloaddir)) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), @@ -116,7 +95,7 @@ def test_reposync_download_path(utils): def test_reposync_download_path_slash(utils): reponame = TESTREPO downloaddir = DOWNLOADDIR + '/' - makedirs(downloaddir) + utils.makedirs(downloaddir) assert(os.path.isdir(downloaddir)) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), @@ -193,7 +172,7 @@ def xxxtest_reposync_download_path_norepopath_multiple_repos(utils): def test_reposync_metadata(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), '--download-metadata', @@ -213,9 +192,9 @@ def test_reposync_metadata(utils): def test_reposync_metadata_path(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) mdatadir = METADATADIR - makedirs(mdatadir) + utils.makedirs(mdatadir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), '--download-metadata', @@ -235,10 +214,10 @@ def test_reposync_metadata_path(utils): def test_reposync_delete(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) synced_dir = os.path.join(workdir, reponame) - makedirs(synced_dir) + utils.makedirs(synced_dir) faked_rpm = os.path.join((synced_dir), 'faked-0.1.2.rpm') with open(faked_rpm, 'w') as f: @@ -265,10 +244,10 @@ def test_reposync_delete(utils): def test_reposync_no_delete(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) synced_dir = os.path.join(workdir, reponame) - makedirs(synced_dir) + utils.makedirs(synced_dir) faked_rpm = os.path.join((synced_dir), 'faked-0.1.2.rpm') with open(faked_rpm, 'w') as f: @@ -294,7 +273,7 @@ def test_reposync_no_delete(utils): def test_reposync_gpgcheck(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), @@ -313,7 +292,7 @@ def test_reposync_gpgcheck(utils): def test_reposync_urls(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), @@ -328,7 +307,7 @@ def test_reposync_urls(utils): def test_reposync_create_repo(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), '--download-metadata', @@ -345,7 +324,7 @@ def test_reposync_create_repo(utils): filename = os.path.join(utils.config['repo_path'], "yum.repos.d", REPOFILENAME) baseurl = "file://{}".format(synced_dir) - create_repoconf(filename, baseurl, "synced-repo") + utils.create_repoconf(filename, baseurl, "synced-repo") ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo=synced-repo', @@ -366,7 +345,7 @@ def test_reposync_create_repo(utils): def test_reposync_arch(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) synced_dir = os.path.join(workdir, reponame) if os.path.isdir(synced_dir): @@ -390,7 +369,7 @@ def test_reposync_arch(utils): def test_reposync_arch_others(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) synced_dir = os.path.join(workdir, reponame) if os.path.isdir(synced_dir): @@ -416,7 +395,7 @@ def test_reposync_arch_others(utils): def test_reposync_newest(utils): reponame = TESTREPO workdir = WORKDIR - makedirs(workdir) + utils.makedirs(workdir) ret = utils.run(['tdnf', '--disablerepo=*', '--enablerepo={}'.format(reponame), diff --git a/pytests/tests/test_setopt_reposdir.py b/pytests/tests/test_setopt_reposdir.py index 0bdb75c0..6a3ab7c5 100644 --- a/pytests/tests/test_setopt_reposdir.py +++ b/pytests/tests/test_setopt_reposdir.py @@ -25,32 +25,11 @@ def teardown_test(utils): if os.path.isdir(REPODIR): shutil.rmtree(REPODIR) -# helper to create directory tree without complains when it exists: -def makedirs(d): - try: - os.makedirs(d) - except OSError as e: - if e.errno != errno.EEXIST: - raise - -def create_repoconf(filename, baseurl, name): - templ = """ -[{name}] -name=Test Repo -baseurl={baseurl} -enabled=1 -gpgcheck=0 -metadata_expire=86400 -ui_repoid_vars=basearch -""" - with open(filename, "w") as f: - f.write(templ.format(name=name, baseurl=baseurl)) - def test_setopt_reposdir(utils): - makedirs(REPODIR) - create_repoconf(os.path.join(REPODIR, REPOFILENAME), - "http://foo.bar.com/packages", - REPONAME) + utils.makedirs(REPODIR) + utils.create_repoconf(os.path.join(REPODIR, REPOFILENAME), + "http://foo.bar.com/packages", + REPONAME) ret = utils.run(['tdnf', '--setopt=reposdir={}'.format(REPODIR), 'repolist']) assert(REPONAME in "\n".join(ret['stdout'])) diff --git a/solv/defines.h b/solv/defines.h index 283df9fb..c2a4493b 100644 --- a/solv/defines.h +++ b/solv/defines.h @@ -2,7 +2,7 @@ #define __SOLV_DEFINES_H__ #define SYSTEM_REPO_NAME "@System" -#define CMDLINE_REPO_NAME "@commandline" +#define CMDLINE_REPO_NAME "@cmdline" #define SOLV_COOKIE_IDENT "tdnf" #define TDNF_SOLVCACHE_DIR_NAME "solvcache" #define SOLV_COOKIE_LEN 32 diff --git a/tools/cli/lib/parseargs.c b/tools/cli/lib/parseargs.c index 7365df8c..a022e131 100644 --- a/tools/cli/lib/parseargs.c +++ b/tools/cli/lib/parseargs.c @@ -84,6 +84,9 @@ static struct option pstOptions[] = {"debugsolver", no_argument, &_opt.nDebugSolver, 1}, //--debugsolver {"disablerepo", required_argument, 0, 0}, //--disablerepo {"enablerepo", required_argument, 0, 0}, //--enablerepo + {"repo", required_argument, 0, 0}, //--repo + {"repoid", required_argument, 0, 0}, //--repoid (same as --repo) + {"repofrompath", required_argument, 0, 0}, //--repofrompath {"errorlevel", required_argument, 0, 'e'}, //-e --errorlevel {"help", no_argument, 0, 'h'}, //-h --help {"installroot", required_argument, 0, 'i'}, //--installroot @@ -390,7 +393,8 @@ ParseOption( } else if ((!strcasecmp(pszName, "metadata-path")) || (!strcasecmp(pszName, "download-path")) || - (!strcasecmp(pszName, "arch"))) + (!strcasecmp(pszName, "arch")) || + (!strcasecmp(pszName, "repofrompath"))) { dwError = AddSetOptWithValues(pCmdArgs, CMDOPT_KEYVALUE, @@ -398,6 +402,15 @@ ParseOption( optarg); BAIL_ON_CLI_ERROR(dwError); } + else if ((!strcasecmp(pszName, "repoid")) || + (!strcasecmp(pszName, "repo"))) + { + dwError = AddSetOptWithValues(pCmdArgs, + CMDOPT_KEYVALUE, + "repoid", + optarg); + BAIL_ON_CLI_ERROR(dwError); + } else if (!strcasecmp(pszName, "setopt")) { if (!optarg)