Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Repository class refactoring #95

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft

WIP: Repository class refactoring #95

wants to merge 18 commits into from

Conversation

arthurmco
Copy link
Collaborator

@arthurmco arthurmco commented Jan 27, 2025

Refactor the repository class based on @dhilst 's modeling


Edit

Context:

  • I (Daniel) generalized RepoManager over the repository type and the runner,
  • Because of that I generalized Cluster over the runner too, this is intentional for us to track who is executing code through clusters's runner
  • The Cluster's new parameter propagated through the code base, I used BaseRunner in most places where it doesn't matter, and added a type parameter where it does (where it is getting the runner or the repo manager)

TODO:

  • Replace the old implementation of RepoManager with the new implementation
  • Remove the dependency Runner from Cluster, if something is depending on the cluster's runner to run commands we'll find out, this something should be running commands on its own

Edit

More context:

  • I added namespaces cloyster::models and cloyster::services to start splitting the code according to the model-view-presenter architecture
  • I moved the files so they correspond to their namespaces
  • I'm looking into the RepoManager logic now and how the clients use it
  • I added cloyster::services::files::KeyFile class to encapsulate the glibmm implementation of keyfile, we must use it without leaking implementation details (glib types)

@arthurmco arthurmco requested a review from dhilst January 27, 2025 14:11
@arthurmco arthurmco self-assigned this Jan 27, 2025
return file;
} catch (Glib::FileError& e) {
throw repository_exception(
std::format("Could not load repository file {} ({})",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmt::format.


void ELRepoFile::read()
{
printf("reading\n");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No...

Comment on lines 113 to 120
for (const auto& r : m_repositories) {
std::print("repo found '{}'\n", r.group);
std::print("\tname: '{}'\n", r.name);
std::print("\tbaseurl: '{}'\n", r.baseURL.value_or("null"));
std::print("\tmetalink: '{}'\n", r.metalink.value_or("null"));
std::print("\tenabled: {}\n", r.enabled);
std::print("\tgpg: (check: {}, key: {})\n", r.gpgcheck, r.gpgkey);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this debug? If yes add #ifndef NDEBUG. Also we are using fmt::format instead and use the LOG_DEBUG directive.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was glibmm test code I forgot to remove.

include/cloysterhpc/services/repo.h Outdated Show resolved Hide resolved
include/cloysterhpc/services/repo.h Outdated Show resolved Hide resolved
m_repositories.push_back(std::move(repo));
}

for (const auto& r : m_repositories) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid using only r as variable name. Usually we use it for well defined counters, like: i, j and k. Or for iterators, like it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only code for toying with glibmm

In real life, this would not be like this

(This comment applies to every printf/fmt::format comment above)

@viniciusferrao
Copy link
Owner

Refactor the repository class based on @dhilst 's modeling

The modeling was done by the three of us. You included!

Comment on lines 61 to 67
/**
* Repository file class
*/
template <class Repo> class RepoFile {
protected:
std::filesystem::path m_path;
std::vector<Repo> m_repositories;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are mixing up "repository" and File class

  • Remove the Repo type parameter
  • Rename RepoFile to File
  • Remove m_repositories member

This class only wraps file I/O, it must not know anything about repositories

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this?

class File {
protected:
    std::filesystem::path m_path;
public:
    RepoFile(const std::filesystem::path& path)
        : m_path(path)
    {}

    virtual void read() {}
    virtual void write() {}
};

(Me including the repositories list there was a mistake... I already removed it)

Copy link
Owner

@viniciusferrao viniciusferrao Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially, there will be an entity named something like "File" on the namespace "cloysterhpc" that will handle basic file operations. Open, close, write, read, chmod. There's a lot of that on glib and we may use them:

https://gnome.pages.gitlab.gnome.org/glibmm/classGio_1_1File.html
https://gnome.pages.gitlab.gnome.org/glibmm/group__FileUtils.html
https://gnome.pages.gitlab.gnome.org/glibmm/group__UriUtils.html

I do believe that GIO will solve almost everything.

Comment on lines 95 to 107
class ELRepoFile : public RepoFile<ELRepo> {
private:
Glib::RefPtr<Glib::KeyFile> loadFile();

public:
ELRepoFile(const std::filesystem::path& path)
: RepoFile(path)
{
}

void read() override;
void write() override;
};
Copy link
Collaborator

@dhilst dhilst Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have an abstract RepoFile which extends the File, adds the m_repositories generic member, and with parse unparse methods, read is super read followed by parse and write is unparse followed by super write

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::filesystem::path is convertible to std::string or const char*. We must use it. It's the right API.

However the file class that be dependent on std::filesystem::path and not the derived one.

Copy link
Collaborator

@dhilst dhilst Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear

  • parse loads data from the file into the m_repositories member
  • unparse loads the m_repositories member into the file

Also, @arthurmco, add overloads to parse and unparse which I/O into istringstream ostringstream instead of directly into the file so we can test without touching the disks. I don't know if this is possible because I don't know the interface of glibmm if it can load/unload keyfiles from strings, can it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is possible; glibmm can load keyhole data from a string.

Comment on lines 90 to 92
auto metalink = (file->has_key(repogroup, "metalink"))
? std::make_optional(file->get_string(repogroup, "metalink"))
: std::nullopt;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optionals are really cool. Add a free function for reading an optional from keyfiles

Copy link
Owner

@viniciusferrao viniciusferrao Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm an idiot. I have too much difficulty reading ternary operators. That's a technical debt in my mind.

The std::nullopt should be inside a std::make_optional? I don't know.

Copy link
Collaborator

@dhilst dhilst Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is okay, you can read this like this if (file->has_key(repogroup, "metalink")) { metalink = std::make_optional(file->get_string(repogroup, "metalink")) } else { metalink = std::nullopt; }. metalink is an optional set to the metalink property if it exists in the file, or set to nullopt if not. This is pretty general, we'll want to use std::optional to represent optional values in the conf file, so I'm suggesting that we create a function for that

inline std::optional<std::string> get_optional_string(
  const KeyFile& fil,
  const std::string& group,
  const std::string& key)
{
  if (fil->has_key(group, key)) {
    return fil->get_string(group, key);
  }
  return std::nullopt;
}

Copy link
Owner

@viniciusferrao viniciusferrao Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optional is got with the .value() accessor, right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but glib keyfile is not using optional here, I guess the interface is older than std::optional

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but glib keyfile is not using optional here, I guess the interface is older than std::optional

Yes it is. But we are talking about the same issue? That our API shuould provide access with std::optional and inside the class we encapsulate that? If that's the case yes I do agree.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you saying for us to extend glibmm file interface and add this as a member function?

Comment on lines 81 to 86
std::vector<ELRepo> ELRepoFile::parse(const std::stringstream& ss)
{
m_file = Glib::KeyFile::create();
m_file->load_from_data(ss.str().c_str());
return this->parseData();
}
Copy link
Collaborator

@dhilst dhilst Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, now

  • Add m_repositories member as a vector of ELRepo with a getter
  • The getter should load the data into the member if the member is empty and return at the end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside of ELRepo?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside ELRepoFile

struct ELRepo {
std::string group;
std::string name;
std::optional<std::string> baseURL;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

base_url

Comment on lines 118 to 119
void unparse( const std::vector<ELRepo>& repositories );
void unparse( const std::vector<ELRepo>& repositories, std::stringstream& ss );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void unparse( const std::vector<ELRepo>& repositories );
void unparse( const std::vector<ELRepo>& repositories, std::stringstream& ss );
void unparse(const std::vector<ELRepo>& repositories);
void unparse(const std::vector<ELRepo>& repositories, std::stringstream& ss);

Comment on lines 95 to 100
auto get_optional_string
= [this](auto group, auto key) -> std::optional<Glib::ustring> {
return m_file->has_key(group, key)
? std::make_optional(m_file->get_string(group, key))
: std::nullopt;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why this captures this, anyway, move it to functions.cpp

Copy link
Collaborator

@dhilst dhilst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API looks good, there are a few points

  • Make sure to remove the prints
  • Rename the ELReo to ELCloneRepo
  • Remove the PR from draft

Copy link
Owner

@viniciusferrao viniciusferrao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue that I've observed. The virtual classes should be on its own files. This needs to be fixed.


std::vector<ELRepo> ELRepoFile::parse()
{
this->read();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need "this"?


if (name.empty()) {
throw repository_exception(std::format(
"Could not load repo name from repo '{}' at file {}",
"Could not load repo name from repo '{}' at m_file {}",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more than a DEBUG message for the developer than to the user. For the user it should be something more friendly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you suggest?

@@ -164,6 +166,9 @@ std::string findAndReplace(const std::string_view& source,
*/
void copyFile(std::filesystem::path source, std::filesystem::path destination);

std::optional<Glib::ustring> readKeyfileString(Glib::RefPtr<Glib::KeyFile> file,
const std::string_view& group, const std::string_view& key);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std:string_view is already a pointer to a string. It should not be passed as const ref.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that. I thought it was pointer+length. It will be fixed

/**
* Repository file class
*
* This class should parse the repository data
*/
class ELRepoFile : GenericFile {
private:
private:
Glib::RefPtr<Glib::KeyFile> m_file;

std::vector<ELRepo> parseData();
void unparseData(const std::vector<ELRepo>&);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing the variable name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name is not needed in the declaration and the context is obvious, but I will fixed because of conventions

@@ -351,4 +351,12 @@ void copyFile(std::filesystem::path source, std::filesystem::path destination)
}
}

std::optional<Glib::ustring> readKeyfileString(Glib::RefPtr<Glib::KeyFile> file,
const std::string_view& group, const std::string_view& key)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to be const ref.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arthurmco arthurmco requested a review from dhilst February 4, 2025 13:44
@arthurmco arthurmco marked this pull request as ready for review February 4, 2025 13:45
Copy link
Owner

@viniciusferrao viniciusferrao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up adding a lot of comments.

I think we should think a little bit more on this implementation.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class name must match de filename. And also the #ifndef guards.

I would recommend using a namespace to avoid clashing.

Comment on lines 26 to 27
virtual void read() { }
virtual void write() { }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be = 0? I can't find the implementation in other files, only the specialization. It should be pure virtual.

{
}

virtual void read() { }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think read will not modify the state of the object right? Should it be const?

std::filesystem::path m_path;

public:
explicit GenericFile(const std::filesystem::path& path)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we missing overloads? std::string_view, std::string and const char *? Should it be templated with Concepts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not add the overloads if it is not being used, I would make the m_path const though

virtual void read() { }
virtual void write() { }

virtual ~GenericFile() = default;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you defaulted a destructor, AFAIK, the move operations are by default deleted. I think we should define the move operations:

GenericFile(GenericFile&&) = default;
GenericFile& operator=(GenericFile&&) = default;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

Comment on lines +18 to +23
void ELRepoFile::parse()
{
read();

m_repositories = parseData();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read() and parse() are both public. However parse() calls read() obfuscating it.

Is that the behaviour you intended to?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some thoughts about this class, I will review its API after looking into the repo manager. Read is public because it inherits public from GenericFile I guess.

repo.enabled = enabled;
repo.gpgcheck = gpgcheck;
repo.gpgkey = gpgkey;
repositories.push_back(std::move(repo));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emplace_back.

Comment on lines 56 to 65
ELCloneRepo repo;
repo.group = repogroup.raw();
repo.name = name.raw();
repo.metalink
= metalink.transform([](const auto& v) { return v.raw(); });
repo.base_url
= baseurl.transform([](const auto& v) { return v.raw(); });
repo.enabled = enabled;
repo.gpgcheck = gpgcheck;
repo.gpgkey = gpgkey;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't be better to use an initializer list?

This approach may lead to uninitialized values.

}

[[nodiscard]] const std::vector<ELCloneRepo>&
ELRepoFile::getRepositoriesConst() const
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the qualifier in the method name is a very bad approach.

m_file->load_from_file(m_path.string());
} catch (Glib::FileError& e) {
throw repository_exception(
std::format("Could not load repository file {} ({})",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmt::format.

@dhilst dhilst assigned dhilst and unassigned arthurmco Feb 7, 2025
@@ -84,4 +86,6 @@ class PresenterNodesOperationalSystem : public Presenter {
std::unique_ptr<Cluster>& model, std::unique_ptr<Newt>& view);
};

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -0,0 +1,18 @@
//
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this file

@@ -164,6 +172,9 @@ std::string findAndReplace(const std::string_view& source,
*/
void copyFile(std::filesystem::path source, std::filesystem::path destination);

std::optional<Glib::ustring> readKeyfileString(Glib::RefPtr<Glib::KeyFile> file,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this

#include <cloysterhpc/ofed.h>
#include <cloysterhpc/queuesystem/pbs.h>
#include <cloysterhpc/queuesystem/slurm.h>
#include <cloysterhpc/repos.h>
#include <cloysterhpc/runner.h>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move runner to services

@@ -23,4 +26,6 @@ class PBS : public QueueSystem {
explicit PBS(const Cluster& cluster);
};

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
};
}; // namespace cloyster::models

@@ -42,4 +43,6 @@ class PresenterQueueSystem : public Presenter {
std::unique_ptr<Cluster>& model, std::unique_ptr<Newt>& view);
};

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -24,3 +25,5 @@ class PresenterRepository : public Presenter {
PresenterRepository(
std::unique_ptr<Cluster>& model, std::unique_ptr<Newt>& view);
};

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -38,4 +40,6 @@ class PresenterTime : public Presenter {
PresenterTime(std::unique_ptr<Cluster>& model, std::unique_ptr<Newt>& view);
};

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -29,5 +30,6 @@ class PresenterWelcome : public Presenter {
PresenterWelcome(
std::unique_ptr<Cluster>& model, std::unique_ptr<Newt>& view);
};
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

Comment on lines +22 to +28
template <typename File>
concept IsKeyFileWriteable = requires(File& file, const std::string& group, const std::string& key, bool bvalue, const std::string& svalue, const std::optional<std::string>& soptvalue)
{
file.setString(group, key, svalue);
file.setString(group, key, soptvalue);
file.setBoolean(group, key, bvalue);
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identation

@@ -605,6 +607,8 @@ void AnswerFile::loadPostfix()
postfix.key_file = m_ini.getValue("postfix", "smtpd_tls_key_file", false);
}

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

Comment on lines +123 to +153
// void Cluster::initRepoManager()
// {
// if (cloyster::dryRun) {
// m_repos.emplace(RepoManager<repository, DryRunner>(*getRunner(), m_headnode.getOS()));
// } else {
// m_repos.emplace(RepoManager<repository, Runner>(*getRunner(), m_headnode.getOS()));
// }
// }

// @TODO Remove this after as part of the repository refactoring
// template <typename Runner>
// RepoManager<repository, Runner>& Cluster<Runner>::getRepoManager()
// {
// if (!m_repos) {
// initRepoManager();
// }
//
// return m_repos.value();
// }

// RepoManager<repository, BaseRunner>& Cluster::getRepoManager()
// {
// if (!m_repos) {
// m_repos = cloyster::getRepoManager();
// };
// return m_repos.value();
// }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented code

@@ -66,3 +70,5 @@ void CPU::setThreadsPerCore(size_t threadsPerCore)
{
m_threadsPerCore = threadsPerCore;
}

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add closing namespace comment

@@ -54,3 +57,5 @@ void Headnode::setBootTarget(Headnode::BootTarget bootTarget)
{
m_bootTarget = bootTarget;
}

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -46,3 +48,5 @@ void Node::setNodeRootPassword(
{
m_node_root_password = nodeRootPassword;
}

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -267,4 +269,6 @@ void OS::printData() const
LOG_DEBUG("Major Version: {}", m_majorVersion)
LOG_DEBUG("Minor Version: {}", m_minorVersion)
}

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -17,3 +19,5 @@ void PBS::setExecutionPlace(ExecutionPlace executionPlace)
}

PBS::ExecutionPlace PBS::getExecutionPlace(void) { return m_executionPlace; }

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -20,3 +22,5 @@ void QueueSystem::setDefaultQueue(std::string_view defaultQueue)
}

std::string_view QueueSystem::getDefaultQueue(void) { return m_defaultQueue; }

};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -1,12 +1,15 @@
/*
* o
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* o

@@ -173,3 +176,5 @@ TEST_SUITE("Test FQDN")
}
}
}

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

@@ -59,3 +60,5 @@ void SLURM::startServer()
runCommand("systemctl start munge");
runCommand("systemctl start slurmctld");
}

}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace closing comment

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this file

Comment on lines +24 to +33
const std::vector<services::repos::BaseRepository>& repo_names = manager->listRepos();

auto repo_names = manager.listRepos();
std::vector<std::tuple<std::string, std::string, bool>> repo_strings;

std::transform(repo_names.begin(), repo_names.end(),
std::back_inserter(repo_strings), [](auto entry) {
return std::make_tuple(std::string { entry.id },
std::string { entry.name }, entry.enabled);
std::back_inserter(repo_strings), [](auto& entry) {
return std::make_tuple(std::string { entry.id() },
std::string { entry.name() }, entry.enabled() );
});
assert(repo_strings.size() > 0); // reminder to fix this
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this

I'm favoring to move stuff to models/ or services/
folders/namespaces. There is a lot of moves to do
yet but this already outlines some structure
Comment on lines +31 to +44
// @TODO: Move this to its own file
/**
* @brief ParserNoExc<P, T, E> means: P can parse and unparse Ts from streams.
* The parsers are not allowed to throw exceptions, it must return errors of
* type E
*/
template <typename Parser_, typename T, typename E>
concept ParserNoExc = requires(Parser_ parser, std::istream& input,
std::ostream& output, const T& parsed) {
{ parser.parse(input) } noexcept -> std::same_as<std::expected<T, E>>;
{
parser.unparse(parsed, output)
} noexcept -> std::same_as<std::expected<void, E>>;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can go away

Comment on lines +45 to +47

// @TODO: Move this to its own file
/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this comment

{ parser.unparse(unparseInput, unparseOutput) } -> std::same_as<void>;
};

// @TODO: Move this to its own file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// @TODO: Move this to its own file

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
21 Security Hotspots

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants