Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #372 from fbergkemper/dev/fbergkemper/master/cli-i…
…mprovements

dird: Sort resource names in prompt lists
  • Loading branch information
fbergkemper committed Dec 17, 2019
2 parents ea327fe + 82c730d commit 2173e6f
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 10 deletions.
93 changes: 83 additions & 10 deletions core/src/dird/ua_select.cc
Expand Up @@ -35,9 +35,13 @@
#include "dird/storage.h"
#include "dird/ua_input.h"
#include "dird/ua_select.h"
#include "dird/ua_select.h"
#include "lib/edit.h"
#include "lib/parse_conf.h"
#include "lib/util.h"

#include <algorithm>
#include <string>
#include <vector>

namespace directordaemon {

Expand Down Expand Up @@ -152,6 +156,7 @@ StorageResource* select_storage_resource(UaContext* ua, bool autochanger_only)
{
StorageResource* store;
char name[MAX_NAME_LENGTH];
std::vector<std::string> storage_resource_names;

if (autochanger_only) {
StartPrompt(ua, _("The defined Autochanger Storage resources are:\n"));
Expand All @@ -165,12 +170,18 @@ StorageResource* select_storage_resource(UaContext* ua, bool autochanger_only)
if (autochanger_only && !store->autochanger) {
continue;
} else {
AddPrompt(ua, store->resource_name_);
storage_resource_names.emplace_back(store->resource_name_);
}
}
}
UnlockRes(my_config);

SortCaseInsensitive(storage_resource_names);

for (auto& resource_name : storage_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Storage"), _("Select Storage resource"), name,
sizeof(name)) < 0) {
return NULL;
Expand All @@ -187,17 +198,24 @@ FilesetResource* select_fileset_resource(UaContext* ua)
{
FilesetResource* fs;
char name[MAX_NAME_LENGTH];
std::vector<std::string> fileset_resource_names;

StartPrompt(ua, _("The defined FileSet resources are:\n"));

LockRes(my_config);
foreach_res (fs, R_FILESET) {
if (ua->AclAccessOk(FileSet_ACL, fs->resource_name_)) {
AddPrompt(ua, fs->resource_name_);
fileset_resource_names.emplace_back(fs->resource_name_);
}
}
UnlockRes(my_config);

SortCaseInsensitive(fileset_resource_names);

for (auto& resource_name : fileset_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("FileSet"), _("Select FileSet resource"), name,
sizeof(name)) < 0) {
return NULL;
Expand Down Expand Up @@ -270,6 +288,7 @@ JobResource* select_enable_disable_job_resource(UaContext* ua, bool enable)
{
JobResource* job;
char name[MAX_NAME_LENGTH];
std::vector<std::string> job_resource_names;

StartPrompt(ua, _("The defined Job resources are:\n"));

Expand All @@ -279,10 +298,16 @@ JobResource* select_enable_disable_job_resource(UaContext* ua, bool enable)
if (job->enabled == enable) { /* Already enabled/disabled? */
continue; /* yes, skip */
}
AddPrompt(ua, job->resource_name_);
job_resource_names.emplace_back(job->resource_name_);
}
UnlockRes(my_config);

SortCaseInsensitive(job_resource_names);

for (auto& resource_name : job_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) <
0) {
return NULL;
Expand All @@ -300,17 +325,24 @@ JobResource* select_job_resource(UaContext* ua)
{
JobResource* job;
char name[MAX_NAME_LENGTH];
std::vector<std::string> job_resource_names;

StartPrompt(ua, _("The defined Job resources are:\n"));

LockRes(my_config);
foreach_res (job, R_JOB) {
if (ua->AclAccessOk(Job_ACL, job->resource_name_)) {
AddPrompt(ua, job->resource_name_);
job_resource_names.emplace_back(job->resource_name_);
}
}
UnlockRes(my_config);

SortCaseInsensitive(job_resource_names);

for (auto& resource_name : job_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) <
0) {
return NULL;
Expand Down Expand Up @@ -347,18 +379,25 @@ JobResource* select_restore_job_resource(UaContext* ua)
{
JobResource* job;
char name[MAX_NAME_LENGTH];
std::vector<std::string> restore_job_names;

StartPrompt(ua, _("The defined Restore Job resources are:\n"));

LockRes(my_config);
foreach_res (job, R_JOB) {
if (job->JobType == JT_RESTORE &&
ua->AclAccessOk(Job_ACL, job->resource_name_)) {
AddPrompt(ua, job->resource_name_);
restore_job_names.emplace_back(job->resource_name_);
}
}
UnlockRes(my_config);

SortCaseInsensitive(restore_job_names);

for (auto& resource_name : restore_job_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
return NULL;
}
Expand All @@ -375,17 +414,24 @@ ClientResource* select_client_resource(UaContext* ua)
{
ClientResource* client;
char name[MAX_NAME_LENGTH];
std::vector<std::string> client_resource_names;

StartPrompt(ua, _("The defined Client resources are:\n"));

LockRes(my_config);
foreach_res (client, R_CLIENT) {
if (ua->AclAccessOk(Client_ACL, client->resource_name_)) {
AddPrompt(ua, client->resource_name_);
client_resource_names.emplace_back(client->resource_name_);
}
}
UnlockRes(my_config);

SortCaseInsensitive(client_resource_names);

for (auto& resource_name : client_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Client"), _("Select Client (File daemon) resource"), name,
sizeof(name)) < 0) {
return NULL;
Expand All @@ -404,6 +450,7 @@ ClientResource* select_enable_disable_client_resource(UaContext* ua,
{
ClientResource* client;
char name[MAX_NAME_LENGTH];
std::vector<std::string> client_resource_names;

StartPrompt(ua, _("The defined Client resources are:\n"));

Expand All @@ -413,10 +460,16 @@ ClientResource* select_enable_disable_client_resource(UaContext* ua,
if (client->enabled == enable) { /* Already enabled/disabled? */
continue; /* yes, skip */
}
AddPrompt(ua, client->resource_name_);
client_resource_names.emplace_back(client->resource_name_);
}
UnlockRes(my_config);

SortCaseInsensitive(client_resource_names);

for (auto& resource_name : client_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Client"), _("Select Client resource"), name,
sizeof(name)) < 0) {
return NULL;
Expand Down Expand Up @@ -461,6 +514,7 @@ ScheduleResource* select_enable_disable_schedule_resource(UaContext* ua,
{
ScheduleResource* sched;
char name[MAX_NAME_LENGTH];
std::vector<std::string> schedule_resource_names;

StartPrompt(ua, _("The defined Schedule resources are:\n"));

Expand All @@ -470,10 +524,16 @@ ScheduleResource* select_enable_disable_schedule_resource(UaContext* ua,
if (sched->enabled == enable) { /* Already enabled/disabled? */
continue; /* yes, skip */
}
AddPrompt(ua, sched->resource_name_);
schedule_resource_names.emplace_back(sched->resource_name_);
}
UnlockRes(my_config);

SortCaseInsensitive(schedule_resource_names);

for (auto& resource_name : schedule_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Schedule"), _("Select Schedule resource"), name,
sizeof(name)) < 0) {
return NULL;
Expand Down Expand Up @@ -883,16 +943,23 @@ PoolResource* select_pool_resource(UaContext* ua)
{
PoolResource* pool;
char name[MAX_NAME_LENGTH];
std::vector<std::string> pool_resource_names;

StartPrompt(ua, _("The defined Pool resources are:\n"));
LockRes(my_config);
foreach_res (pool, R_POOL) {
if (ua->AclAccessOk(Pool_ACL, pool->resource_name_)) {
AddPrompt(ua, pool->resource_name_);
pool_resource_names.emplace_back(pool->resource_name_);
}
}
UnlockRes(my_config);

SortCaseInsensitive(pool_resource_names);

for (auto& resource_name : pool_resource_names) {
AddPrompt(ua, std::move(resource_name));
}

if (DoPrompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) <
0) {
return NULL;
Expand Down Expand Up @@ -1026,6 +1093,12 @@ void AddPrompt(UaContext* ua, const char* prompt)
ua->prompt[ua->num_prompts++] = strdup(prompt);
}

void AddPrompt(UaContext* ua, std::string&& prompt)
{
std::string p{prompt};
AddPrompt(ua, p.c_str());
}

/**
* Display prompts and get user's choice
*
Expand Down
1 change: 1 addition & 0 deletions core/src/dird/ua_select.h
Expand Up @@ -48,6 +48,7 @@ bool SelectClientDbr(UaContext* ua, ClientDbRecord* cr);

void StartPrompt(UaContext* ua, const char* msg);
void AddPrompt(UaContext* ua, const char* prompt);
void AddPrompt(UaContext* ua, std::string&& prompt);
int DoPrompt(UaContext* ua,
const char* automsg,
const char* msg,
Expand Down
17 changes: 17 additions & 0 deletions core/src/lib/util.cc
Expand Up @@ -1087,3 +1087,20 @@ const char* last_path_separator(const char* str)
}
return NULL;
}

void StringToLowerCase(std::string& s)
{
for (auto& c : s) { c = std::tolower(c); }
}

void SortCaseInsensitive(std::vector<std::string>& v)
{
if (v.empty()) { return; }

std::sort(v.begin(), v.end(), [](const std::string& a, const std::string& b) {
std::string x{a}, y{b};
StringToLowerCase(x);
StringToLowerCase(y);
return x < y;
});
}
1 change: 1 addition & 0 deletions core/src/lib/util.h
Expand Up @@ -66,5 +66,6 @@ POOLMEM* edit_job_codes(JobControlRecord* jcr,
job_code_callback_t job_code_callback = NULL);
void SetWorkingDirectory(const char* wd);
const char* last_path_separator(const char* str);
void SortCaseInsensitive(std::vector<std::string>& v);

#endif // BAREOS_LIB_UTIL_H_
8 changes: 8 additions & 0 deletions core/src/tests/CMakeLists.txt
Expand Up @@ -385,3 +385,11 @@ if(NOT HAVE_WIN32 AND NOT client-only)
${GTEST_MAIN_LIBRARIES}
)
endif() # NOT HAVE_WIN32 AND NOT client-only


if(NOT client-only)
bareos_add_test(
sort_stringvector LINK_LIBRARIES bareos ${GTEST_LIBRARIES}
${GTEST_MAIN_LIBRARIES}
)
endif() # NOT client-only
42 changes: 42 additions & 0 deletions core/src/tests/sort_stringvector.cc
@@ -0,0 +1,42 @@
/*
BAREOS® - Backup Archiving REcovery Open Sourced
Copyright (C) 2019-2019 Bareos GmbH & Co. KG
This program is Free Software; you can redistribute it and/or
modify it under the terms of version three of the GNU Affero General Public
License as published by the Free Software Foundation, which is
listed in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#if defined(HAVE_MINGW)
#include "include/bareos.h"
#include "gtest/gtest.h"
#else
#include "gtest/gtest.h"
#include "include/bareos.h"
#endif

#include "lib/util.h"

TEST(sort_stringvector, sort_ascending)
{
std::vector<std::string> v{"Zfs", "EXT2", "ext3", "ext4", "xfs", "AFS"};
SortCaseInsensitive(v);

EXPECT_STREQ(v[0].c_str(), "AFS");
EXPECT_STREQ(v[1].c_str(), "EXT2");
EXPECT_STREQ(v[2].c_str(), "ext3");
EXPECT_STREQ(v[3].c_str(), "ext4");
EXPECT_STREQ(v[4].c_str(), "xfs");
EXPECT_STREQ(v[5].c_str(), "Zfs");
}

0 comments on commit 2173e6f

Please sign in to comment.