Browse Source

Add repo-1.dds.pizza as a pkg remote on initial db migration:

- Add a getenv() abstraction that is more versatile than the std:: one
default_compile_flags
vector-of-bool 3 years ago
parent
commit
8c026b10e5
11 changed files with 156 additions and 40 deletions
  1. +3
    -2
      src/dds.main.cpp
  2. +14
    -0
      src/dds/pkg/db.cpp
  3. +65
    -5
      src/dds/pkg/remote.cpp
  4. +2
    -0
      src/dds/pkg/remote.hpp
  5. +18
    -0
      src/dds/util/env.cpp
  6. +23
    -0
      src/dds/util/env.hpp
  7. +9
    -19
      src/dds/util/paths.linux_fbsd.cpp
  8. +5
    -6
      src/dds/util/paths.macos.cpp
  9. +3
    -2
      src/dds/util/result.cpp
  10. +4
    -1
      tools/dds_ci/dds.py
  11. +10
    -5
      tools/dds_ci/proc.py

+ 3
- 2
src/dds.main.cpp View File

#include <dds/cli/dispatch_main.hpp> #include <dds/cli/dispatch_main.hpp>
#include <dds/cli/options.hpp> #include <dds/cli/options.hpp>
#include <dds/util/env.hpp>
#include <dds/util/log.hpp> #include <dds/util/log.hpp>
#include <dds/util/output.hpp> #include <dds/util/output.hpp>
#include <dds/util/signal.hpp> #include <dds/util/signal.hpp>
#include <locale> #include <locale>


static void load_locale() { static void load_locale() {
auto lang = std::getenv("LANG");
auto lang = dds::getenv("LANG");
if (!lang) { if (!lang) {
return; return;
} }
try { try {
std::locale::global(std::locale(lang));
std::locale::global(std::locale(*lang));
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
// No locale with the given name // No locale with the given name
return; return;

+ 14
- 0
src/dds/pkg/db.cpp View File

#include <dds/error/errors.hpp> #include <dds/error/errors.hpp>
#include <dds/error/nonesuch.hpp> #include <dds/error/nonesuch.hpp>
#include <dds/solve/solve.hpp> #include <dds/solve/solve.hpp>
#include <dds/util/env.hpp>
#include <dds/util/log.hpp> #include <dds/util/log.hpp>
#include <dds/util/paths.hpp> #include <dds/util/paths.hpp>


namespace nsql = neo::sqlite3; namespace nsql = neo::sqlite3;
using namespace neo::sqlite3::literals; using namespace neo::sqlite3::literals;


namespace dds {

void add_init_repo(nsql::database_ref db) noexcept;

} // namespace dds

namespace { namespace {


void migrate_repodb_1(nsql::database& db) { void migrate_repodb_1(nsql::database& db) {
} }
meta["version"] = current_database_version; meta["version"] = current_database_version;
exec(db.prepare("UPDATE dds_cat_meta SET meta=?"), meta.dump()); exec(db.prepare("UPDATE dds_cat_meta SET meta=?"), meta.dump());
tr.commit();

if (version < 3 && !getenv_bool("DDS_NO_ADD_INITIAL_REPO")) {
// Version 3 introduced remote repositories. If we're updating to 3, add that repo now
dds_log(info, "Downloading initial repository");
dds::add_init_repo(db);
}
} }


} // namespace } // namespace

+ 65
- 5
src/dds/pkg/remote.cpp View File

#include <dds/util/log.hpp> #include <dds/util/log.hpp>
#include <dds/util/result.hpp> #include <dds/util/result.hpp>


#include <boost/leaf/handle_exception.hpp>
#include <fansi/styled.hpp> #include <fansi/styled.hpp>
#include <fmt/ostream.h>
#include <neo/event.hpp> #include <neo/event.hpp>
#include <neo/io/stream/buffers.hpp> #include <neo/io/stream/buffers.hpp>
#include <neo/io/stream/file.hpp> #include <neo/io/stream/file.hpp>
} }


void dds::remove_remote(pkg_db& pkdb, std::string_view name) { void dds::remove_remote(pkg_db& pkdb, std::string_view name) {
auto& db = pkdb.database();
neo::sqlite3::transaction_guard tr{db};
auto& db = pkdb.database();
nsql::transaction_guard tr{db};
auto get_rowid_st = db.prepare("SELECT remote_id FROM dds_pkg_remotes WHERE name = ?"); auto get_rowid_st = db.prepare("SELECT remote_id FROM dds_pkg_remotes WHERE name = ?");
get_rowid_st.bindings()[1] = name; get_rowid_st.bindings()[1] = name;
auto row = neo::sqlite3::unpack_single_opt<std::int64_t>(get_rowid_st);
auto row = nsql::unpack_single_opt<std::int64_t>(get_rowid_st);
if (!row) { if (!row) {
BOOST_LEAF_THROW_EXCEPTION( // BOOST_LEAF_THROW_EXCEPTION( //
make_user_error<errc::no_catalog_remote_info>("There is no remote with name '{}'", make_user_error<errc::no_catalog_remote_info>("There is no remote with name '{}'",
name), name),
[&] { [&] {
auto all_st = db.prepare("SELECT name FROM dds_pkg_remotes"); auto all_st = db.prepare("SELECT name FROM dds_pkg_remotes");
auto tups = neo::sqlite3::iter_tuples<std::string>(all_st);
auto tups = nsql::iter_tuples<std::string>(all_st);
auto names = tups | ranges::views::transform([](auto&& tup) { auto names = tups | ranges::views::transform([](auto&& tup) {
auto&& [n] = tup; auto&& [n] = tup;
return n; return n;
}); });
} }
auto [rowid] = *row; auto [rowid] = *row;
neo::sqlite3::exec(db.prepare("DELETE FROM dds_pkg_remotes WHERE remote_id = ?"), rowid);
nsql::exec(db.prepare("DELETE FROM dds_pkg_remotes WHERE remote_id = ?"), rowid);
}

void dds::add_init_repo(nsql::database_ref db) noexcept {
std::string_view init_repo = "https://repo-1.dds.pizza";
// _Do not_ let errors stop us from continuing
bool okay = boost::leaf::try_catch(
[&]() -> bool {
try {
auto remote = pkg_remote::connect(init_repo);
remote.store(db);
update_all_remotes(db);
return true;
} catch (...) {
capture_exception();
}
},
[](http_status_error err, http_response_info resp, neo::url url) {
dds_log(error,
"An HTTP error occurred while adding the initial repository [{}]: HTTP Status "
"{} {}",
err.what(),
url.to_string(),
resp.status,
resp.status_message);
return false;
},
[](e_sqlite3_error_exc e, neo::url url) {
dds_log(error,
"Error accessing remote database while adding initial repository: {}: {}",
url.to_string(),
e.message);
return false;
},
[](e_sqlite3_error_exc e) {
dds_log(error, "Unexpected database error: {}", e.message);
return false;
},
[](e_system_error_exc e, network_origin conn) {
dds_log(error,
"Error communicating with [.br.red[{}://{}:{}]`]: {}"_styled,
conn.protocol,
conn.hostname,
conn.port,
e.message);
return false;
},
[](boost::leaf::diagnostic_info const& diag) -> int {
dds_log(critical, "Unhandled error while adding initial package repository: ", diag);
throw;
});
if (!okay) {
dds_log(warn, "We failed to add the initial package repository [{}]", init_repo);
dds_log(warn, "No remote packages will be available until the above issue is resolved.");
dds_log(
warn,
"The remote package repository can be added again with [.br.yellow[dds pkg repo add \"{}\"]]"_styled,
init_repo);
}
} }

+ 2
- 0
src/dds/pkg/remote.hpp View File

void update_all_remotes(neo::sqlite3::database_ref); void update_all_remotes(neo::sqlite3::database_ref);
void remove_remote(pkg_db& db, std::string_view name); void remove_remote(pkg_db& db, std::string_view name);


void add_init_repo(neo::sqlite3::database_ref db) noexcept;

} // namespace dds } // namespace dds

+ 18
- 0
src/dds/util/env.cpp View File

#include "./env.hpp"

#include <neo/utility.hpp>

#include <cstdlib>

std::optional<std::string> dds::getenv(const std::string& varname) noexcept {
auto cptr = std::getenv(varname.data());
if (cptr) {
return std::string(cptr);
}
return {};
}

bool dds::getenv_bool(const std::string& varname) noexcept {
auto s = getenv(varname);
return s == neo::oper::any_of("1", "true", "on", "TRUE", "ON", "YES", "yes");
}

+ 23
- 0
src/dds/util/env.hpp View File

#pragma once

#include <neo/concepts.hpp>

#include <optional>
#include <string>

namespace dds {

std::optional<std::string> getenv(const std::string& env) noexcept;

bool getenv_bool(const std::string& env) noexcept;

template <neo::invocable Func>
std::string getenv(const std::string& name, Func&& fn) noexcept(noexcept(fn())) {
auto val = getenv(name);
if (!val) {
return std::string(fn());
}
return *val;
}

} // namespace dds

+ 9
- 19
src/dds/util/paths.linux_fbsd.cpp View File



#include "./paths.hpp" #include "./paths.hpp"


#include <dds/util/env.hpp>
#include <dds/util/log.hpp> #include <dds/util/log.hpp>


#include <cstdlib> #include <cstdlib>


fs::path dds::user_home_dir() { fs::path dds::user_home_dir() {
static auto ret = []() -> fs::path { static auto ret = []() -> fs::path {
auto home_env = std::getenv("HOME");
if (!home_env) {
return fs::absolute(dds::getenv("HOME", [] {
dds_log(error, "No HOME environment variable set!"); dds_log(error, "No HOME environment variable set!");
return "/"; return "/";
}
return fs::absolute(fs::path(home_env));
}));
}(); }();
return ret; return ret;
} }


fs::path dds::user_data_dir() { fs::path dds::user_data_dir() {
static auto ret = []() -> fs::path { static auto ret = []() -> fs::path {
auto xdg_data_home = std::getenv("XDG_DATA_HOME");
if (xdg_data_home) {
return fs::absolute(fs::path(xdg_data_home));
}
return user_home_dir() / ".local/share";
return fs::absolute(
dds::getenv("XDG_DATA_HOME", [] { return user_home_dir() / ".local/share"; }));
}(); }();
return ret; return ret;
} }


fs::path dds::user_cache_dir() { fs::path dds::user_cache_dir() {
static auto ret = []() -> fs::path { static auto ret = []() -> fs::path {
auto xdg_cache_home = std::getenv("XDG_CACHE_HOME");
if (xdg_cache_home) {
return fs::absolute(fs::path(xdg_cache_home));
}
return user_home_dir() / ".cache";
return fs::absolute(
dds::getenv("XDG_CACHE_HOME", [] { return user_home_dir() / ".cache"; }));
}(); }();
return ret; return ret;
} }


fs::path dds::user_config_dir() { fs::path dds::user_config_dir() {
static auto ret = []() -> fs::path { static auto ret = []() -> fs::path {
auto xdg_config_home = std::getenv("XDG_CONFIG_HOME");
if (xdg_config_home) {
return fs::absolute(fs::path(xdg_config_home));
}
return user_home_dir() / ".config";
return fs::absolute(
dds::getenv("XDG_CONFIG_HOME", [] { return user_home_dir() / ".config"; }));
}(); }();
return ret; return ret;
} }

+ 5
- 6
src/dds/util/paths.macos.cpp View File



#include "./paths.hpp" #include "./paths.hpp"


#include <dds/util/env.hpp>
#include <dds/util/log.hpp> #include <dds/util/log.hpp>


#include <cstdlib> #include <cstdlib>


fs::path dds::user_home_dir() { fs::path dds::user_home_dir() {
static auto ret = []() -> fs::path { static auto ret = []() -> fs::path {
auto home_env = std::getenv("HOME");
if (!home_env) {
dds_log(warn, "No HOME environment variable set!");
return fs::absolute(dds::getenv("HOME", [] {
dds_log(error, "No HOME environment variable set!");
return "/"; return "/";
}
return fs::absolute(fs::path(home_env));
}));
}(); }();
return ret; return ret;
} }
fs::path dds::user_cache_dir() { return user_home_dir() / "Library/Caches"; } fs::path dds::user_cache_dir() { return user_home_dir() / "Library/Caches"; }
fs::path dds::user_config_dir() { return user_home_dir() / "Preferences"; } fs::path dds::user_config_dir() { return user_home_dir() / "Preferences"; }


#endif
#endif

+ 3
- 2
src/dds/util/result.cpp View File

#include "./result.hpp" #include "./result.hpp"


#include <dds/util/env.hpp>
#include <dds/util/log.hpp> #include <dds/util/log.hpp>


#include <fmt/ostream.h> #include <fmt/ostream.h>


void dds::write_error_marker(std::string_view error) noexcept { void dds::write_error_marker(std::string_view error) noexcept {
dds_log(trace, "[error marker {}]", error); dds_log(trace, "[error marker {}]", error);
auto efile_path = std::getenv("DDS_WRITE_ERROR_MARKER");
auto efile_path = dds::getenv("DDS_WRITE_ERROR_MARKER");
if (efile_path) { if (efile_path) {
std::ofstream outfile{efile_path, std::ios::binary};
std::ofstream outfile{*efile_path, std::ios::binary};
fmt::print(outfile, "{}", error); fmt::print(outfile, "{}", error);
} }
} }

+ 4
- 1
tools/dds_ci/dds.py View File

import multiprocessing import multiprocessing
import shutil import shutil
import os
from pathlib import Path from pathlib import Path
import copy import copy
from typing import Optional, TypeVar, Iterable from typing import Optional, TypeVar, Iterable


def run(self, args: proc.CommandLine, *, cwd: Optional[Pathish] = None) -> None: def run(self, args: proc.CommandLine, *, cwd: Optional[Pathish] = None) -> None:
"""Execute the 'dds' executable with the given arguments""" """Execute the 'dds' executable with the given arguments"""
proc.check_run([self.path, args], cwd=cwd or self.default_cwd)
env = os.environ.copy()
env['DDS_NO_ADD_INITIAL_REPO'] = '1'
proc.check_run([self.path, args], cwd=cwd or self.default_cwd, env=env)


def catalog_json_import(self, path: Path) -> None: def catalog_json_import(self, path: Path) -> None:
"""Run 'catalog import' to import the given JSON. Only applicable to older 'dds'""" """Run 'catalog import' to import the given JSON. Only applicable to older 'dds'"""

+ 10
- 5
tools/dds_ci/proc.py View File

from pathlib import PurePath from pathlib import PurePath
from typing import Iterable, Union, Optional, Iterator, NoReturn, Sequence
from typing import Iterable, Union, Optional, Iterator, NoReturn, Sequence, Mapping
from typing_extensions import Protocol from typing_extensions import Protocol
import subprocess import subprocess


assert False, f'Invalid command line element: {repr(cmd)}' assert False, f'Invalid command line element: {repr(cmd)}'




def run(*cmd: CommandLine, cwd: Optional[Pathish] = None, check: bool = False) -> ProcessResult:
def run(*cmd: CommandLine,
cwd: Optional[Pathish] = None,
check: bool = False,
env: Optional[Mapping[str, str]] = None) -> ProcessResult:
command = list(flatten_cmd(cmd)) command = list(flatten_cmd(cmd))
res = subprocess.run(command, cwd=cwd, check=False)
res = subprocess.run(command, cwd=cwd, check=False, env=env)
if res.returncode and check: if res.returncode and check:
raise_error(res) raise_error(res)
return res return res
raise subprocess.CalledProcessError(proc.returncode, proc.args, output=proc.stdout, stderr=proc.stderr) raise subprocess.CalledProcessError(proc.returncode, proc.args, output=proc.stdout, stderr=proc.stderr)




def check_run(*cmd: CommandLine, cwd: Optional[Pathish] = None) -> ProcessResult:
return run(cmd, cwd=cwd, check=True)
def check_run(*cmd: CommandLine,
cwd: Optional[Pathish] = None,
env: Optional[Mapping[str, str]] = None) -> ProcessResult:
return run(cmd, cwd=cwd, check=True, env=env)

Loading…
Cancel
Save