mirror of
https://github.com/subsurface/subsurface.git
synced 2025-01-31 17:33:24 +00:00
core: convert git_info to std::string
Quite a bit of fallout in users of this structure. Conveniently, since git-access.cpp is now C++ we can move some helpers from the monstrous qthelper.cpp to git-access.cpp. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
ae299d5e66
commit
a123589efb
13 changed files with 290 additions and 319 deletions
|
@ -202,17 +202,18 @@ void CheckCloudConnection::gotContinent(QNetworkReply *reply)
|
|||
extern "C" bool canReachCloudServer(struct git_info *info)
|
||||
{
|
||||
if (verbose)
|
||||
qWarning() << "Cloud storage: checking connection to cloud server" << info->url;
|
||||
qWarning() << "Cloud storage: checking connection to cloud server" << info->url.c_str();
|
||||
bool connection = CheckCloudConnection().checkServer();
|
||||
if (strstr(info->url, prefs.cloud_base_url) == nullptr) {
|
||||
if (info->url.find(prefs.cloud_base_url) == std::string::npos) {
|
||||
// we switched the cloud URL - likely because we couldn't reach the server passed in
|
||||
// the strstr with the offset is designed so we match the right component in the name;
|
||||
// the cloud_base_url ends with a '/', so we need the text starting at "git/..."
|
||||
char *newremote = format_string("%s%s", prefs.cloud_base_url, strstr(info->url, "org/git/") + 4);
|
||||
if (verbose)
|
||||
qDebug() << "updating remote to: " << newremote;
|
||||
free((void*)info->url);
|
||||
info->url = newremote;
|
||||
size_t pos = info->url.find("org/git/");
|
||||
if (pos != std::string::npos) {
|
||||
info->url = format_string_std("%s%s", prefs.cloud_base_url, info->url.c_str() + pos + 4);
|
||||
if (verbose)
|
||||
qDebug() << "updating remote to: " << info->url.c_str();
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "dive.h"
|
||||
#include "divelog.h"
|
||||
#include "subsurface-string.h"
|
||||
#include "format.h"
|
||||
#include "errorhelper.h"
|
||||
#include "file.h"
|
||||
#include "git-access.h"
|
||||
|
@ -250,7 +251,7 @@ static int parse_file_buffer(const char *filename, std::string &mem, struct dive
|
|||
return parse_xml_buffer(filename, mem.data(), mem.size(), log, NULL);
|
||||
}
|
||||
|
||||
extern "C" bool remote_repo_uptodate(const char *filename, struct git_info *info)
|
||||
bool remote_repo_uptodate(const char *filename, struct git_info *info)
|
||||
{
|
||||
std::string current_sha = saved_git_id;
|
||||
|
||||
|
@ -278,14 +279,11 @@ extern "C" int parse_file(const char *filename, struct divelog *log)
|
|||
* Opening the cloud storage repository failed for some reason
|
||||
* give up here and don't send errors about git repositories
|
||||
*/
|
||||
if (info.is_subsurface_cloud) {
|
||||
cleanup_git_info(&info);
|
||||
if (info.is_subsurface_cloud)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int ret = git_load_dives(&info, log);
|
||||
cleanup_git_info(&info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <git2.h>
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#include "subsurface-string.h"
|
||||
#include "format.h"
|
||||
#include "membuffer.h"
|
||||
#include "strndup.h"
|
||||
#include "qthelper.h"
|
||||
|
@ -117,12 +121,20 @@ static int transfer_progress_cb(const git_transfer_progress *stats, void *)
|
|||
// the initial push to sync the repos is mapped to 10% of overall progress
|
||||
static int push_transfer_progress_cb(unsigned int current, unsigned int total, size_t, void *)
|
||||
{
|
||||
char buf[80];
|
||||
snprintf(buf, sizeof(buf), translate("gettextFromC", "Transfer to storage (%d/%d)"), current, total);
|
||||
return git_storage_update_progress(buf);
|
||||
std::string buf = casprintf_loc(translate("gettextFromC", "Transfer to storage (%d/%d)"), current, total);
|
||||
return git_storage_update_progress(buf.c_str());
|
||||
}
|
||||
|
||||
extern "C" char *get_local_dir(const char *url, const char *branch)
|
||||
std::string normalize_cloud_name(const std::string &remote_in)
|
||||
{
|
||||
// replace ssrf-cloud-XX.subsurface... names with cloud.subsurface... names
|
||||
// that trailing '/' is to match old code
|
||||
QString ri = QString::fromStdString(remote_in);
|
||||
ri.replace(QRegularExpression(CLOUD_HOST_PATTERN), CLOUD_HOST_GENERIC "/");
|
||||
return ri.toStdString();
|
||||
}
|
||||
|
||||
std::string get_local_dir(const std::string &url, const std::string &branch)
|
||||
{
|
||||
SHA_CTX ctx;
|
||||
unsigned char hash[20];
|
||||
|
@ -133,9 +145,6 @@ extern "C" char *get_local_dir(const char *url, const char *branch)
|
|||
// which server to pick changed, or because the user is on a different continent),
|
||||
// then the hash and therefore the local directory would change. To prevent that
|
||||
// from happening, normalize the cloud string to always use the old default name.
|
||||
// That's trivial with QString operations and painful to do right in plain C, so
|
||||
// let's be lazy and call a C++ helper function
|
||||
// just remember to free the string we get back
|
||||
std::string remote = normalize_cloud_name(url);
|
||||
|
||||
// That zero-byte update is so that we don't get hash
|
||||
|
@ -143,19 +152,18 @@ extern "C" char *get_local_dir(const char *url, const char *branch)
|
|||
SHA1_Init(&ctx);
|
||||
SHA1_Update(&ctx, remote.c_str(), remote.size());
|
||||
SHA1_Update(&ctx, "", 1);
|
||||
SHA1_Update(&ctx, branch, strlen(branch));
|
||||
SHA1_Update(&ctx, branch.c_str(), branch.size());
|
||||
SHA1_Final(hash, &ctx);
|
||||
return format_string("%s/cloudstorage/%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
return format_string_std("%s/cloudstorage/%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
system_default_directory(),
|
||||
hash[0], hash[1], hash[2], hash[3],
|
||||
hash[4], hash[5], hash[6], hash[7]);
|
||||
}
|
||||
|
||||
static char *move_local_cache(struct git_info *info)
|
||||
static std::string move_local_cache(struct git_info *info)
|
||||
{
|
||||
char *old_path = get_local_dir(info->url, info->branch);
|
||||
char *new_path = move_away(old_path);
|
||||
free(old_path);
|
||||
std::string old_path = get_local_dir(info->url, info->branch);
|
||||
std::string new_path = move_away(old_path);
|
||||
return new_path;
|
||||
}
|
||||
|
||||
|
@ -248,15 +256,12 @@ extern "C" int credential_ssh_cb(git_cred **out,
|
|||
|
||||
// TODO: We need a way to differentiate between password and private key authentication
|
||||
if (allowed_types & GIT_CREDTYPE_SSH_KEY) {
|
||||
char *priv_key = format_string("%s/%s", system_default_directory(), "ssrf_remote.key");
|
||||
if (!access(priv_key, F_OK)) {
|
||||
std::string priv_key = std::string(system_default_directory()) + "/ssrf_remote.key";
|
||||
if (!access(priv_key.c_str(), F_OK)) {
|
||||
if (exceeded_auth_attempts())
|
||||
return GIT_EUSER;
|
||||
int ret = git_cred_ssh_key_new(out, username, NULL, priv_key, passphrase);
|
||||
free(priv_key);
|
||||
return ret;
|
||||
return git_cred_ssh_key_new(out, username, NULL, priv_key.c_str(), passphrase);
|
||||
}
|
||||
free(priv_key);
|
||||
}
|
||||
|
||||
if (allowed_types & GIT_CREDTYPE_USERPASS_PLAINTEXT) {
|
||||
|
@ -346,7 +351,7 @@ static int try_to_git_merge(struct git_info *info, git_reference **local_p, git_
|
|||
git_commit *local_commit, *remote_commit, *base_commit;
|
||||
git_index *merged_index;
|
||||
git_merge_options merge_options;
|
||||
struct membuffer msg = { 0, 0, NULL};
|
||||
struct membufferpp msg;
|
||||
|
||||
if (verbose) {
|
||||
char outlocal[41], outremote[41];
|
||||
|
@ -450,7 +455,6 @@ static int try_to_git_merge(struct git_info *info, git_reference **local_p, git_
|
|||
git_signature_free(author);
|
||||
if (verbose)
|
||||
report_info("git storage: successfully merged repositories");
|
||||
free_buffer(&msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -458,7 +462,6 @@ diverged_error:
|
|||
return report_error("%s", translate("gettextFromC", "Remote storage and local data diverged"));
|
||||
|
||||
write_error:
|
||||
free_buffer(&msg);
|
||||
return report_error(translate("gettextFromC", "Remote storage and local data diverged. Error: writing the data failed (%s)"), giterr_last()->message);
|
||||
}
|
||||
|
||||
|
@ -467,11 +470,10 @@ write_error:
|
|||
// and ask them to retry the operation (which will then refresh the data from the cloud server)
|
||||
static int cleanup_local_cache(struct git_info *info)
|
||||
{
|
||||
char *backup_path = move_local_cache(info);
|
||||
report_info("git storage: problems with local cache, moved to %s", backup_path);
|
||||
std::string backup_path = move_local_cache(info);
|
||||
report_info("git storage: problems with local cache, moved to %s", backup_path.c_str());
|
||||
report_error("%s", translate("gettextFromC", "Problems with local cache of Subsurface cloud data"));
|
||||
report_error(translate("gettextFromC", "Moved cache data to %s. Please try the operation again."), backup_path);
|
||||
free(backup_path);
|
||||
report_error(translate("gettextFromC", "Moved cache data to %s. Please try the operation again."), backup_path.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -576,17 +578,17 @@ static int check_remote_status(struct git_info *info, git_remote *origin)
|
|||
if (verbose)
|
||||
report_info("git storage: check remote status\n");
|
||||
|
||||
if (git_branch_lookup(&local_ref, info->repo, info->branch, GIT_BRANCH_LOCAL)) {
|
||||
report_info("git storage: branch %s is missing in local repo", info->branch);
|
||||
if (git_branch_lookup(&local_ref, info->repo, info->branch.c_str(), GIT_BRANCH_LOCAL)) {
|
||||
report_info("git storage: branch %s is missing in local repo", info->branch.c_str());
|
||||
if (info->is_subsurface_cloud)
|
||||
return cleanup_local_cache(info);
|
||||
else
|
||||
return report_error("Git cache branch %s no longer exists", info->branch);
|
||||
return report_error("Git cache branch %s no longer exists", info->branch.c_str());
|
||||
}
|
||||
if (git_branch_upstream(&remote_ref, local_ref)) {
|
||||
/* so there is no upstream branch for our branch; that's a problem.
|
||||
* let's push our branch */
|
||||
report_info("git storage: branch %s is missing in remote, pushing branch", info->branch);
|
||||
report_info("git storage: branch %s is missing in remote, pushing branch", info->branch.c_str());
|
||||
git_strarray refspec;
|
||||
git_reference_list(&refspec, info->repo);
|
||||
git_push_options opts = GIT_PUSH_OPTIONS_INIT;
|
||||
|
@ -608,62 +610,69 @@ static int check_remote_status(struct git_info *info, git_remote *origin)
|
|||
return error;
|
||||
}
|
||||
|
||||
static std::string getProxyString()
|
||||
{
|
||||
if (prefs.proxy_type == QNetworkProxy::HttpProxy) {
|
||||
if (prefs.proxy_auth)
|
||||
return format_string_std("http://%s:%s@%s:%d", prefs.proxy_user, prefs.proxy_pass,
|
||||
prefs.proxy_host, prefs.proxy_port);
|
||||
else
|
||||
return format_string_std("http://%s:%d", prefs.proxy_host, prefs.proxy_port);
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
/* this is (so far) only used by the git storage tests to remove a remote branch
|
||||
* it will print out errors, but not return an error (as this isn't a function that
|
||||
* we test as part of the tests, it's a helper to not leave loads of dead branches on
|
||||
* the server)
|
||||
*/
|
||||
extern "C" void delete_remote_branch(git_repository *repo, const char *remote, const char *branch)
|
||||
void delete_remote_branch(git_repository *repo, const std::string &remote, const std::string &branch)
|
||||
{
|
||||
int error;
|
||||
char *proxy_string;
|
||||
git_remote *origin;
|
||||
git_config *conf;
|
||||
|
||||
/* set up the config and proxy information in order to connect to the server */
|
||||
git_repository_config(&conf, repo);
|
||||
if (getProxyString(&proxy_string)) {
|
||||
git_config_set_string(conf, "http.proxy", proxy_string);
|
||||
free(proxy_string);
|
||||
std::string proxy_string = getProxyString();
|
||||
if (!proxy_string.empty()) {
|
||||
git_config_set_string(conf, "http.proxy", proxy_string.c_str());
|
||||
} else {
|
||||
git_config_delete_entry(conf, "http.proxy");
|
||||
}
|
||||
if (git_remote_lookup(&origin, repo, "origin")) {
|
||||
report_info("git storage: repository '%s' origin lookup failed (%s)", remote, giterr_last() ? giterr_last()->message : "(unspecified)");
|
||||
report_info("git storage: repository '%s' origin lookup failed (%s)", remote.c_str(), giterr_last() ? giterr_last()->message : "(unspecified)");
|
||||
return;
|
||||
}
|
||||
/* fetch the remote state */
|
||||
git_fetch_options f_opts = GIT_FETCH_OPTIONS_INIT;
|
||||
auth_attempt = 0;
|
||||
f_opts.callbacks.credentials = credential_https_cb;
|
||||
error = git_remote_fetch(origin, NULL, &f_opts, NULL);
|
||||
if (error) {
|
||||
if (git_remote_fetch(origin, NULL, &f_opts, NULL)) {
|
||||
report_info("git storage: remote fetch failed (%s)\n", giterr_last() ? giterr_last()->message : "authentication failed");
|
||||
return;
|
||||
}
|
||||
/* delete the remote branch by pushing to ":refs/heads/<branch>" */
|
||||
git_strarray refspec;
|
||||
char *branch_ref = format_string(":refs/heads/%s", branch);
|
||||
std::string branch_ref = std::string(":refs/heads/") + branch;
|
||||
char *dummy = branch_ref.data();
|
||||
refspec.count = 1;
|
||||
refspec.strings = &branch_ref;
|
||||
refspec.strings = &dummy;
|
||||
git_push_options p_opts = GIT_PUSH_OPTIONS_INIT;
|
||||
auth_attempt = 0;
|
||||
p_opts.callbacks.credentials = credential_https_cb;
|
||||
error = git_remote_push(origin, &refspec, &p_opts);
|
||||
free(branch_ref);
|
||||
if (error) {
|
||||
report_info("git storage: unable to delete branch '%s'", branch);
|
||||
if (git_remote_push(origin, &refspec, &p_opts)) {
|
||||
report_info("git storage: unable to delete branch '%s'", branch.c_str());
|
||||
report_info("git storage: error was (%s)\n", giterr_last() ? giterr_last()->message : "(unspecified)");
|
||||
}
|
||||
git_remote_free(origin);
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" int sync_with_remote(struct git_info *info)
|
||||
int sync_with_remote(struct git_info *info)
|
||||
{
|
||||
int error;
|
||||
git_remote *origin;
|
||||
char *proxy_string;
|
||||
git_config *conf;
|
||||
|
||||
if (git_local_only) {
|
||||
|
@ -672,14 +681,14 @@ extern "C" int sync_with_remote(struct git_info *info)
|
|||
return 0;
|
||||
}
|
||||
if (verbose)
|
||||
report_info("git storage: sync with remote %s[%s]\n", info->url, info->branch);
|
||||
report_info("git storage: sync with remote %s[%s]\n", info->url.c_str(), info->branch.c_str());
|
||||
git_storage_update_progress(translate("gettextFromC", "Sync with cloud storage"));
|
||||
git_repository_config(&conf, info->repo);
|
||||
if (info->transport == RT_HTTPS && getProxyString(&proxy_string)) {
|
||||
std::string proxy_string = getProxyString();
|
||||
if (info->transport == RT_HTTPS && !proxy_string.empty()) {
|
||||
if (verbose)
|
||||
report_info("git storage: set proxy to \"%s\"\n", proxy_string);
|
||||
git_config_set_string(conf, "http.proxy", proxy_string);
|
||||
free(proxy_string);
|
||||
report_info("git storage: set proxy to \"%s\"\n", proxy_string.c_str());
|
||||
git_config_set_string(conf, "http.proxy", proxy_string.c_str());
|
||||
} else {
|
||||
if (verbose)
|
||||
report_info("git storage: delete proxy setting\n");
|
||||
|
@ -693,9 +702,9 @@ extern "C" int sync_with_remote(struct git_info *info)
|
|||
error = git_remote_lookup(&origin, info->repo, "origin");
|
||||
if (error) {
|
||||
const char *msg = giterr_last()->message;
|
||||
report_info("git storage: repo %s origin lookup failed with: %s", info->url, msg);
|
||||
report_info("git storage: repo %s origin lookup failed with: %s", info->url.c_str(), msg);
|
||||
if (!info->is_subsurface_cloud)
|
||||
report_error("Repository '%s' origin lookup failed (%s)", info->url, msg);
|
||||
report_error("Repository '%s' origin lookup failed (%s)", info->url.c_str(), msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -726,7 +735,7 @@ extern "C" int sync_with_remote(struct git_info *info)
|
|||
if (info->is_subsurface_cloud)
|
||||
report_error("Cannot sync with cloud server, working with offline copy");
|
||||
else
|
||||
report_error("Unable to fetch remote '%s'", info->url);
|
||||
report_error("Unable to fetch remote '%s'", info->url.c_str());
|
||||
// If we returned GIT_EUSER during authentication, giterr_last() returns NULL
|
||||
report_info("git storage: remote fetch failed (%s)\n", giterr_last() ? giterr_last()->message : "authentication failed");
|
||||
// Since we failed to sync with online repository, enter offline mode
|
||||
|
@ -748,18 +757,17 @@ static bool update_local_repo(struct git_info *info)
|
|||
if (!git_repository_head(&head, info->repo)) {
|
||||
const char *name;
|
||||
if (!git_branch_name(&name, head)) {
|
||||
if (strcmp(name, info->branch)) {
|
||||
char *branchref = format_string("refs/heads/%s", info->branch);
|
||||
report_info("git storage: setting cache branch from '%s' to '%s'", name, info->branch);
|
||||
git_repository_set_head(info->repo, branchref);
|
||||
free(branchref);
|
||||
if (info->branch != name) {
|
||||
std::string branchref = "refs/heads/" + info->branch;
|
||||
report_info("git storage: setting cache branch from '%s' to '%s'", name, info->branch.c_str());
|
||||
git_repository_set_head(info->repo, branchref.c_str());
|
||||
}
|
||||
}
|
||||
git_reference_free(head);
|
||||
}
|
||||
/* make sure we have the correct origin - the cloud server URL could have changed */
|
||||
if (git_remote_set_url(info->repo, "origin", info->url)) {
|
||||
report_info("git storage: failed to update origin to '%s'", info->url);
|
||||
if (git_remote_set_url(info->repo, "origin", info->url.c_str())) {
|
||||
report_info("git storage: failed to update origin to '%s'", info->url.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -771,7 +779,6 @@ static bool update_local_repo(struct git_info *info)
|
|||
|
||||
static int repository_create_cb(git_repository **out, const char *path, int bare, void *)
|
||||
{
|
||||
char *proxy_string;
|
||||
git_config *conf;
|
||||
|
||||
int ret = git_repository_init(out, path, bare);
|
||||
|
@ -782,11 +789,11 @@ static int repository_create_cb(git_repository **out, const char *path, int bare
|
|||
}
|
||||
|
||||
git_repository_config(&conf, *out);
|
||||
if (getProxyString(&proxy_string)) {
|
||||
std::string proxy_string = getProxyString();
|
||||
if (!proxy_string.empty()) {
|
||||
if (verbose)
|
||||
report_info("git storage: set proxy to \"%s\"\n", proxy_string);
|
||||
git_config_set_string(conf, "http.proxy", proxy_string);
|
||||
free(proxy_string);
|
||||
report_info("git storage: set proxy to \"%s\"\n", proxy_string.c_str());
|
||||
git_config_set_string(conf, "http.proxy", proxy_string.c_str());
|
||||
} else {
|
||||
if (verbose)
|
||||
report_info("git storage: delete proxy setting\n");
|
||||
|
@ -800,34 +807,30 @@ static int repository_create_cb(git_repository **out, const char *path, int bare
|
|||
static bool create_and_push_remote(struct git_info *info)
|
||||
{
|
||||
git_config *conf;
|
||||
char *variable_name, *head;
|
||||
|
||||
if (verbose)
|
||||
report_info("git storage: create and push remote\n");
|
||||
|
||||
/* first make sure the directory for the local cache exists */
|
||||
subsurface_mkdir(info->localdir);
|
||||
subsurface_mkdir(info->localdir.c_str());
|
||||
|
||||
head = format_string("refs/heads/%s", info->branch);
|
||||
std::string head = "refs/heads/" + info->branch;
|
||||
|
||||
/* set up the origin to point to our remote */
|
||||
git_repository_init_options init_opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
|
||||
init_opts.origin_url = info->url;
|
||||
init_opts.initial_head = head;
|
||||
init_opts.origin_url = info->url.c_str();
|
||||
init_opts.initial_head = head.c_str();
|
||||
|
||||
/* now initialize the repository with */
|
||||
git_repository_init_ext(&info->repo, info->localdir, &init_opts);
|
||||
git_repository_init_ext(&info->repo, info->localdir.c_str(), &init_opts);
|
||||
|
||||
/* create a config so we can set the remote tracking branch */
|
||||
git_repository_config(&conf, info->repo);
|
||||
variable_name = format_string("branch.%s.remote", info->branch);
|
||||
git_config_set_string(conf, variable_name, "origin");
|
||||
free(variable_name);
|
||||
std::string variable_name = "branch." + info->branch + ".remote";
|
||||
git_config_set_string(conf, variable_name.c_str(), "origin");
|
||||
|
||||
variable_name = format_string("branch.%s.merge", info->branch);
|
||||
git_config_set_string(conf, variable_name, head);
|
||||
free(head);
|
||||
free(variable_name);
|
||||
variable_name = "branch." + info->branch + ".merge";
|
||||
git_config_set_string(conf, variable_name.c_str(), head.c_str());
|
||||
|
||||
/* finally create an empty commit and push it to the remote */
|
||||
if (do_git_save(info, false, true))
|
||||
|
@ -853,18 +856,18 @@ static bool create_local_repo(struct git_info *info)
|
|||
opts.repository_cb = repository_create_cb;
|
||||
opts.fetch_opts.callbacks.certificate_check = certificate_check_cb;
|
||||
|
||||
opts.checkout_branch = info->branch;
|
||||
opts.checkout_branch = info->branch.c_str();
|
||||
if (info->is_subsurface_cloud && !canReachCloudServer(info)) {
|
||||
report_info("git storage: cannot reach remote server");
|
||||
return false;
|
||||
}
|
||||
if (verbose > 1)
|
||||
report_info("git storage: calling git_clone()\n");
|
||||
error = git_clone(&info->repo, info->url, info->localdir, &opts);
|
||||
error = git_clone(&info->repo, info->url.c_str(), info->localdir.c_str(), &opts);
|
||||
if (verbose > 1)
|
||||
report_info("git storage: returned from git_clone() with return value %d\n", error);
|
||||
if (error) {
|
||||
report_info("git storage: clone of %s failed", info->url);
|
||||
report_info("git storage: clone of %s failed", info->url.c_str());
|
||||
const char *msg = "";
|
||||
if (giterr_last()) {
|
||||
msg = giterr_last()->message;
|
||||
|
@ -872,9 +875,9 @@ static bool create_local_repo(struct git_info *info)
|
|||
} else {
|
||||
report_info("git storage: giterr_last() is null\n");
|
||||
}
|
||||
char *pattern = format_string("reference 'refs/remotes/origin/%s' not found", info->branch);
|
||||
std::string pattern = format_string_std("reference 'refs/remotes/origin/%s' not found", info->branch.c_str());
|
||||
// it seems that we sometimes get 'Reference' and sometimes 'reference'
|
||||
if (includes_string_caseinsensitive(msg, pattern)) {
|
||||
if (includes_string_caseinsensitive(msg, pattern.c_str())) {
|
||||
/* we're trying to open the remote branch that corresponds
|
||||
* to our cloud storage and the branch doesn't exist.
|
||||
* So we need to create the branch and push it to the remote */
|
||||
|
@ -887,19 +890,18 @@ static bool create_local_repo(struct git_info *info)
|
|||
report_error("%s", translate("gettextFromC", "Error connecting to Subsurface cloud storage"));
|
||||
#endif
|
||||
} else {
|
||||
report_error(translate("gettextFromC", "git clone of %s failed (%s)"), info->url, msg);
|
||||
report_error(translate("gettextFromC", "git clone of %s failed (%s)"), info->url.c_str(), msg);
|
||||
}
|
||||
free(pattern);
|
||||
}
|
||||
return !error;
|
||||
}
|
||||
|
||||
static enum remote_transport url_to_remote_transport(const char *remote)
|
||||
static enum remote_transport url_to_remote_transport(const std::string &remote)
|
||||
{
|
||||
/* figure out the remote transport */
|
||||
if (strncmp(remote, "ssh://", 6) == 0)
|
||||
if (starts_with(remote, "ssh://"))
|
||||
return RT_SSH;
|
||||
else if (strncmp(remote, "https://", 8) == 0)
|
||||
else if (starts_with(remote.c_str(), "https://"))
|
||||
return RT_HTTPS;
|
||||
else
|
||||
return RT_OTHER;
|
||||
|
@ -910,24 +912,24 @@ static bool get_remote_repo(struct git_info *info)
|
|||
struct stat st;
|
||||
|
||||
if (verbose > 1) {
|
||||
report_info("git storage: accessing %s\n", info->url);
|
||||
report_info("git storage: accessing %s\n", info->url.c_str());
|
||||
}
|
||||
git_storage_update_progress(translate("gettextFromC", "Synchronising data file"));
|
||||
/* Do we already have a local cache? */
|
||||
if (!subsurface_stat(info->localdir, &st)) {
|
||||
if (!subsurface_stat(info->localdir.c_str(), &st)) {
|
||||
int error;
|
||||
|
||||
if (verbose)
|
||||
report_info("git storage: update local repo\n");
|
||||
|
||||
error = git_repository_open(&info->repo, info->localdir);
|
||||
error = git_repository_open(&info->repo, info->localdir.c_str());
|
||||
if (error) {
|
||||
const char *msg = giterr_last()->message;
|
||||
report_info("git storage: unable to open local cache at %s: %s", info->localdir, msg);
|
||||
report_info("git storage: unable to open local cache at %s: %s", info->localdir.c_str(), msg);
|
||||
if (info->is_subsurface_cloud)
|
||||
(void)cleanup_local_cache(info);
|
||||
else
|
||||
report_error("Unable to open git cache repository at %s: %s", info->localdir, msg);
|
||||
report_error("Unable to open git cache repository at %s: %s", info->localdir.c_str(), msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -955,17 +957,17 @@ static bool get_remote_repo(struct git_info *info)
|
|||
* Remove the user name from the url if it exists, and
|
||||
* save it in 'info->username'.
|
||||
*/
|
||||
static void extract_username(struct git_info *info, char *url)
|
||||
std::string extract_username(struct git_info *info, const std::string &url)
|
||||
{
|
||||
char c;
|
||||
char *p = url;
|
||||
const char *p = url.c_str();
|
||||
|
||||
while ((c = *p++) >= 'a' && c <= 'z')
|
||||
/* nothing */;
|
||||
if (c != ':')
|
||||
return;
|
||||
return url;
|
||||
if (*p++ != '/' || *p++ != '/')
|
||||
return;
|
||||
return url;
|
||||
|
||||
/*
|
||||
* Ok, we found "[a-z]*://" and we think we have a real
|
||||
|
@ -974,38 +976,38 @@ static void extract_username(struct git_info *info, char *url)
|
|||
*/
|
||||
info->transport = url_to_remote_transport(url);
|
||||
|
||||
char *at = strchr(p, '@');
|
||||
const char *at = strchr(p, '@');
|
||||
if (!at)
|
||||
return;
|
||||
return url;
|
||||
|
||||
/* was this the @ that denotes an account? that means it was before the
|
||||
* first '/' after the protocol:// - so let's find a '/' after that and compare */
|
||||
char *slash = strchr(p, '/');
|
||||
const char *slash = strchr(p, '/');
|
||||
if (!slash || at > slash)
|
||||
return;
|
||||
return url;
|
||||
|
||||
/* grab the part between "protocol://" and "@" as encoded email address
|
||||
* (that's our username) and move the rest of the URL forward, remembering
|
||||
* to copy the closing NUL as well */
|
||||
info->username = strndup(p, at - p);
|
||||
memmove(p, at + 1, strlen(at + 1) + 1);
|
||||
info->username = std::string(p, at - p);
|
||||
|
||||
/*
|
||||
* Ugly, ugly. Parsing the remote repo user name also sets
|
||||
* it in the preferences. We should do this somewhere else!
|
||||
*/
|
||||
prefs.cloud_storage_email_encoded = strdup(info->username);
|
||||
prefs.cloud_storage_email_encoded = strdup(info->username.c_str());
|
||||
|
||||
return url.substr(at + 1 - url.c_str());
|
||||
}
|
||||
|
||||
extern "C" void cleanup_git_info(struct git_info *info)
|
||||
git_info::git_info() : repo(nullptr), is_subsurface_cloud(0), transport(RT_LOCAL)
|
||||
{
|
||||
if (info->repo)
|
||||
git_repository_free(info->repo);
|
||||
free((void *)info->url);
|
||||
free((void *)info->branch);
|
||||
free((void *)info->username);
|
||||
free((void *)info->localdir);
|
||||
memset(info, 0, sizeof(*info));
|
||||
}
|
||||
|
||||
git_info::~git_info()
|
||||
{
|
||||
if (repo)
|
||||
git_repository_free(repo);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1018,16 +1020,14 @@ extern "C" void cleanup_git_info(struct git_info *info)
|
|||
* https://host/repo[branch]
|
||||
* file://repo[branch]
|
||||
*/
|
||||
extern "C" bool is_git_repository(const char *filename, struct git_info *info)
|
||||
bool is_git_repository(const char *filename, struct git_info *info)
|
||||
{
|
||||
int flen, blen;
|
||||
int offset = 1;
|
||||
char *url, *branch;
|
||||
|
||||
/* we are looking at a new potential remote, but we haven't synced with it */
|
||||
git_remote_sync_successful = false;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->transport = RT_LOCAL;
|
||||
flen = strlen(filename);
|
||||
if (!flen || filename[--flen] != ']')
|
||||
|
@ -1070,11 +1070,11 @@ extern "C" bool is_git_repository(const char *filename, struct git_info *info)
|
|||
* The actual git reading/writing routines can use this
|
||||
* to generate proper error messages.
|
||||
*/
|
||||
url = format_string("%.*s", flen, filename);
|
||||
branch = format_string("%.*s", blen, filename + flen + offset);
|
||||
std::string url(filename, flen);
|
||||
std::string branch(filename + flen + offset, blen);
|
||||
|
||||
/* Extract the username from the url string */
|
||||
extract_username(info, url);
|
||||
url = extract_username(info, url);
|
||||
|
||||
info->url = url;
|
||||
info->branch = branch;
|
||||
|
@ -1099,10 +1099,10 @@ extern "C" bool is_git_repository(const char *filename, struct git_info *info)
|
|||
*/
|
||||
switch (info->transport) {
|
||||
case RT_LOCAL:
|
||||
info->localdir = strdup(url);
|
||||
info->localdir = url;
|
||||
break;
|
||||
default:
|
||||
info->localdir = get_local_dir(info->url, info->branch);
|
||||
info->localdir = get_local_dir(info->url.c_str(), info->branch).c_str();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1112,19 +1112,19 @@ extern "C" bool is_git_repository(const char *filename, struct git_info *info)
|
|||
*
|
||||
* This is used to create more user friendly error message and warnings.
|
||||
*/
|
||||
info->is_subsurface_cloud = (strstr(info->url, prefs.cloud_base_url) != NULL);
|
||||
info->is_subsurface_cloud = (strstr(info->url.c_str(), prefs.cloud_base_url) != NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool open_git_repository(struct git_info *info)
|
||||
bool open_git_repository(struct git_info *info)
|
||||
{
|
||||
/*
|
||||
* If the repository is local, just open it. There's nothing
|
||||
* else to do.
|
||||
*/
|
||||
if (info->transport == RT_LOCAL) {
|
||||
const char *url = info->localdir;
|
||||
const char *url = info->localdir.c_str();
|
||||
|
||||
if (git_repository_open(&info->repo, url)) {
|
||||
if (verbose)
|
||||
|
@ -1145,15 +1145,13 @@ extern "C" bool open_git_repository(struct git_info *info)
|
|||
return get_remote_repo(info);
|
||||
}
|
||||
|
||||
extern "C" int git_create_local_repo(const char *filename)
|
||||
int git_create_local_repo(const std::string &filename)
|
||||
{
|
||||
git_repository *repo;
|
||||
char *path = strdup(filename);
|
||||
char *branch = strchr(path, '[');
|
||||
if (branch)
|
||||
*branch = '\0';
|
||||
int ret = git_repository_init(&repo, path, false);
|
||||
free(path);
|
||||
|
||||
auto idx = filename.find('[');
|
||||
std::string path = filename.substr(0, idx);
|
||||
int ret = git_repository_init(&repo, path.c_str(), false);
|
||||
if (ret != 0)
|
||||
(void)report_error("Create local repo failed with error code %d", ret);
|
||||
git_repository_free(repo);
|
||||
|
|
|
@ -22,20 +22,38 @@ extern "C" {
|
|||
|
||||
enum remote_transport { RT_LOCAL, RT_HTTPS, RT_SSH, RT_OTHER };
|
||||
|
||||
extern bool git_local_only;
|
||||
extern bool git_remote_sync_successful;
|
||||
extern void clear_git_id(void);
|
||||
extern void set_git_id(const struct git_oid *);
|
||||
void set_git_update_cb(int(*)(const char *));
|
||||
int git_storage_update_progress(const char *text);
|
||||
int get_authorship(git_repository *repo, git_signature **authorp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#include <string>
|
||||
|
||||
struct git_oid;
|
||||
struct git_repository;
|
||||
struct divelog;
|
||||
|
||||
struct git_info {
|
||||
const char *url;
|
||||
const char *branch;
|
||||
const char *username;
|
||||
const char *localdir;
|
||||
std::string url;
|
||||
std::string branch;
|
||||
std::string username;
|
||||
std::string localdir;
|
||||
struct git_repository *repo;
|
||||
unsigned is_subsurface_cloud:1;
|
||||
enum remote_transport transport;
|
||||
git_info();
|
||||
~git_info();
|
||||
};
|
||||
|
||||
extern std::string saved_git_id;
|
||||
extern std::string get_sha(git_repository *repo, const std::string &branch);
|
||||
extern std::string get_local_dir(const std::string &, const std::string &);
|
||||
extern bool is_git_repository(const char *filename, struct git_info *info);
|
||||
extern bool open_git_repository(struct git_info *info);
|
||||
extern bool remote_repo_uptodate(const char *filename, struct git_info *info);
|
||||
|
@ -43,23 +61,7 @@ extern int sync_with_remote(struct git_info *);
|
|||
extern int git_save_dives(struct git_info *, bool select_only);
|
||||
extern int git_load_dives(struct git_info *, struct divelog *log);
|
||||
extern int do_git_save(struct git_info *, bool select_only, bool create_empty);
|
||||
extern void cleanup_git_info(struct git_info *);
|
||||
extern bool git_local_only;
|
||||
extern bool git_remote_sync_successful;
|
||||
extern void clear_git_id(void);
|
||||
extern void set_git_id(const struct git_oid *);
|
||||
void set_git_update_cb(int(*)(const char *));
|
||||
int git_storage_update_progress(const char *text);
|
||||
char *get_local_dir(const char *, const char *);
|
||||
int git_create_local_repo(const char *filename);
|
||||
int get_authorship(git_repository *repo, git_signature **authorp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#include <string>
|
||||
extern std::string saved_git_id;
|
||||
extern std::string get_sha(git_repository *repo, const char *branch);
|
||||
extern int git_create_local_repo(const std::string &filename);
|
||||
|
||||
#endif
|
||||
#endif // GITACCESS_H
|
||||
|
|
|
@ -1895,11 +1895,11 @@ static int do_git_load(git_repository *repo, const char *branch, struct git_pars
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string get_sha(git_repository *repo, const char *branch)
|
||||
std::string get_sha(git_repository *repo, const std::string &branch)
|
||||
{
|
||||
char git_id_buffer[GIT_OID_HEXSZ + 1];
|
||||
git_commit *commit;
|
||||
if (find_commit(repo, branch, &commit))
|
||||
if (find_commit(repo, branch.c_str(), &commit))
|
||||
return std::string();
|
||||
git_oid_tostr(git_id_buffer, sizeof(git_id_buffer), (const git_oid *)commit);
|
||||
return std::string(git_id_buffer);
|
||||
|
@ -1913,7 +1913,7 @@ std::string get_sha(git_repository *repo, const char *branch)
|
|||
* If it is a git repository, we return zero for success,
|
||||
* or report an error and return 1 if the load failed.
|
||||
*/
|
||||
extern "C" int git_load_dives(struct git_info *info, struct divelog *log)
|
||||
int git_load_dives(struct git_info *info, struct divelog *log)
|
||||
{
|
||||
int ret;
|
||||
struct git_parser_state state;
|
||||
|
@ -1921,8 +1921,8 @@ extern "C" int git_load_dives(struct git_info *info, struct divelog *log)
|
|||
state.log = log;
|
||||
|
||||
if (!info->repo)
|
||||
return report_error("Unable to open git repository '%s[%s]'", info->url, info->branch);
|
||||
ret = do_git_load(info->repo, info->branch, &state);
|
||||
return report_error("Unable to open git repository '%s[%s]'", info->url.c_str(), info->branch.c_str());
|
||||
ret = do_git_load(info->repo, info->branch.c_str(), &state);
|
||||
finish_active_dive(&state);
|
||||
finish_active_trip(&state);
|
||||
return ret;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "tag.h"
|
||||
#include "imagedownloader.h"
|
||||
#include "xmlparams.h"
|
||||
#include "core/git-access.h" // for CLOUD_HOST definitions
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QDir>
|
||||
|
@ -331,31 +330,31 @@ extern "C" xsltStylesheetPtr get_stylesheet(const char *name)
|
|||
return xslt;
|
||||
}
|
||||
|
||||
extern "C" char *move_away(const char *old_path)
|
||||
std::string move_away(const std::string &old_path)
|
||||
{
|
||||
if (verbose > 1)
|
||||
qDebug() << "move away" << old_path;
|
||||
QDir oldDir(old_path);
|
||||
qDebug() << "move away" << old_path.c_str();
|
||||
QDir oldDir(old_path.c_str());
|
||||
QDir newDir;
|
||||
QString newPath;
|
||||
std::string newPath;
|
||||
int i = 0;
|
||||
do {
|
||||
newPath = QString(old_path) + QString(".%1").arg(++i);
|
||||
newDir.setPath(newPath);
|
||||
newPath = old_path + "." + std::to_string(++i);
|
||||
newDir.setPath(newPath.c_str());
|
||||
} while(newDir.exists());
|
||||
if (verbose > 1)
|
||||
qDebug() << "renaming to" << newPath;
|
||||
if (!oldDir.rename(old_path, newPath)) {
|
||||
qDebug() << "renaming to" << newPath.c_str();
|
||||
if (!oldDir.rename(old_path.c_str(), newPath.c_str())) {
|
||||
if (verbose)
|
||||
qDebug() << "rename of" << old_path << "to" << newPath << "failed";
|
||||
qDebug() << "rename of" << old_path.c_str() << "to" << newPath.c_str() << "failed";
|
||||
// this next one we only try on Windows... if we are on a different platform
|
||||
// we simply give up and return an empty string
|
||||
#ifdef WIN32
|
||||
if (subsurface_dir_rename(old_path, qPrintable(newPath)) == 0)
|
||||
if (subsurface_dir_rename(old_path.c_str(), newPath.c_str()) == 0)
|
||||
#endif
|
||||
return strdup("");
|
||||
return std::string();
|
||||
}
|
||||
return copy_qstring(newPath);
|
||||
return newPath;
|
||||
}
|
||||
|
||||
std::string get_file_name(const char *fileName)
|
||||
|
@ -1375,31 +1374,6 @@ extern "C" char *cloud_url()
|
|||
return copy_qstring(filename);
|
||||
}
|
||||
|
||||
std::string normalize_cloud_name(const char *remote_in)
|
||||
{
|
||||
// replace ssrf-cloud-XX.subsurface... names with cloud.subsurface... names
|
||||
// that trailing '/' is to match old code
|
||||
QString ri(remote_in);
|
||||
ri.replace(QRegularExpression(CLOUD_HOST_PATTERN), CLOUD_HOST_GENERIC "/");
|
||||
return ri.toStdString();
|
||||
}
|
||||
|
||||
extern "C" bool getProxyString(char **buffer)
|
||||
{
|
||||
if (prefs.proxy_type == QNetworkProxy::HttpProxy) {
|
||||
QString proxy;
|
||||
if (prefs.proxy_auth)
|
||||
proxy = QString("http://%1:%2@%3:%4").arg(prefs.proxy_user).arg(prefs.proxy_pass)
|
||||
.arg(prefs.proxy_host).arg(prefs.proxy_port);
|
||||
else
|
||||
proxy = QString("http://%1:%2").arg(prefs.proxy_host).arg(prefs.proxy_port);
|
||||
if (buffer)
|
||||
*buffer = copy_qstring(proxy);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" void subsurface_mkdir(const char *dir)
|
||||
{
|
||||
QDir directory;
|
||||
|
|
|
@ -103,8 +103,8 @@ extern QString (*changesCallback)();
|
|||
void uiNotification(const QString &msg);
|
||||
std::string get_changes_made();
|
||||
std::string subsurface_user_agent();
|
||||
std::string normalize_cloud_name(const char *remote_in);
|
||||
std::string get_file_name(const char *fileName);
|
||||
std::string move_away(const std::string &path);
|
||||
|
||||
#if defined __APPLE__
|
||||
#define TITLE_OR_TEXT(_t, _m) "", _t + "\n" + _m
|
||||
|
@ -122,12 +122,10 @@ extern "C" {
|
|||
|
||||
struct git_info;
|
||||
|
||||
bool getProxyString(char **buffer);
|
||||
bool canReachCloudServer(struct git_info *);
|
||||
void updateWindowTitle();
|
||||
void subsurface_mkdir(const char *dir);
|
||||
void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName);
|
||||
char *move_away(const char *path);
|
||||
const char *local_file_path(struct picture *picture);
|
||||
char *cloud_url();
|
||||
char *hashfile_name_string();
|
||||
|
|
|
@ -1177,19 +1177,19 @@ static int create_new_commit(struct git_info *info, git_oid *tree_id, bool creat
|
|||
git_commit *commit;
|
||||
git_tree *tree;
|
||||
|
||||
ret = git_branch_lookup(&ref, info->repo, info->branch, GIT_BRANCH_LOCAL);
|
||||
ret = git_branch_lookup(&ref, info->repo, info->branch.c_str(), GIT_BRANCH_LOCAL);
|
||||
switch (ret) {
|
||||
default:
|
||||
return report_error("Bad branch '%s' (%s)", info->branch, strerror(errno));
|
||||
return report_error("Bad branch '%s' (%s)", info->branch.c_str(), strerror(errno));
|
||||
case GIT_EINVALIDSPEC:
|
||||
return report_error("Invalid branch name '%s'", info->branch);
|
||||
return report_error("Invalid branch name '%s'", info->branch.c_str());
|
||||
case GIT_ENOTFOUND: /* We'll happily create it */
|
||||
ref = NULL;
|
||||
parent = try_to_find_parent(saved_git_id.c_str(), info->repo);
|
||||
break;
|
||||
case 0:
|
||||
if (git_reference_peel(&parent, ref, GIT_OBJ_COMMIT))
|
||||
return report_error("Unable to look up parent in branch '%s'", info->branch);
|
||||
return report_error("Unable to look up parent in branch '%s'", info->branch.c_str());
|
||||
|
||||
if (!saved_git_id.empty()) {
|
||||
if (!existing_filename.empty() && verbose)
|
||||
|
@ -1238,8 +1238,8 @@ static int create_new_commit(struct git_info *info, git_oid *tree_id, bool creat
|
|||
git_signature_free(author);
|
||||
|
||||
if (!ref) {
|
||||
if (git_branch_create(&ref, info->repo, info->branch, commit, 0))
|
||||
return report_error("Failed to create branch '%s'", info->branch);
|
||||
if (git_branch_create(&ref, info->repo, info->branch.c_str(), commit, 0))
|
||||
return report_error("Failed to create branch '%s'", info->branch.c_str());
|
||||
}
|
||||
/*
|
||||
* If it's a checked-out branch, try to also update the working
|
||||
|
@ -1253,12 +1253,12 @@ static int create_new_commit(struct git_info *info, git_oid *tree_id, bool creat
|
|||
const git_error *err = giterr_last();
|
||||
const char *errstr = err ? err->message : strerror(errno);
|
||||
report_error("Git branch '%s' is checked out, but worktree is dirty (%s)",
|
||||
info->branch, errstr);
|
||||
info->branch.c_str(), errstr);
|
||||
}
|
||||
}
|
||||
|
||||
if (git_reference_set_target(&ref, ref, &commit_id, "Subsurface save event"))
|
||||
return report_error("Failed to update branch '%s'", info->branch);
|
||||
return report_error("Failed to update branch '%s'", info->branch.c_str());
|
||||
|
||||
/*
|
||||
* if this was the empty commit to initialize a new repo, don't remember the
|
||||
|
@ -1294,14 +1294,14 @@ static int write_git_tree(git_repository *repo, const struct dir *tree, git_oid
|
|||
return ret;
|
||||
}
|
||||
|
||||
extern "C" int do_git_save(struct git_info *info, bool select_only, bool create_empty)
|
||||
int do_git_save(struct git_info *info, bool select_only, bool create_empty)
|
||||
{
|
||||
struct dir tree;
|
||||
git_oid id;
|
||||
bool cached_ok;
|
||||
|
||||
if (!info->repo)
|
||||
return report_error("Unable to open git repository '%s[%s]'", info->url, info->branch);
|
||||
return report_error("Unable to open git repository '%s[%s]'", info->url.c_str(), info->branch.c_str());
|
||||
|
||||
if (verbose)
|
||||
report_info("git storage: do git save\n");
|
||||
|
@ -1335,12 +1335,12 @@ extern "C" int do_git_save(struct git_info *info, bool select_only, bool create_
|
|||
return report_error("creating commit failed");
|
||||
|
||||
/* now sync the tree with the remote server */
|
||||
if (info->url && !git_local_only)
|
||||
if (!info->url.empty() && !git_local_only)
|
||||
return sync_with_remote(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int git_save_dives(struct git_info *info, bool select_only)
|
||||
int git_save_dives(struct git_info *info, bool select_only)
|
||||
{
|
||||
/*
|
||||
* First, just try to open the local git repo without
|
||||
|
@ -1357,7 +1357,7 @@ extern "C" int git_save_dives(struct git_info *info, bool select_only)
|
|||
* at least the local state will be saved early in
|
||||
* case something goes wrong.
|
||||
*/
|
||||
if (!git_repository_open(&info->repo, info->localdir))
|
||||
if (!git_repository_open(&info->repo, info->localdir.c_str()))
|
||||
return do_git_save(info, select_only, false);
|
||||
|
||||
/*
|
||||
|
@ -1369,7 +1369,7 @@ extern "C" int git_save_dives(struct git_info *info, bool select_only)
|
|||
* This shouldn't be the common case.
|
||||
*/
|
||||
if (!open_git_repository(info))
|
||||
return report_error(translate("gettextFromC", "Failed to save dives to %s[%s] (%s)"), info->url, info->branch, strerror(errno));
|
||||
return report_error(translate("gettextFromC", "Failed to save dives to %s[%s] (%s)"), info->url.c_str(), info->branch.c_str(), strerror(errno));
|
||||
|
||||
return do_git_save(info, select_only, false);
|
||||
}
|
||||
|
|
|
@ -823,7 +823,6 @@ extern "C" int save_dives_logic(const char *filename, const bool select_only, bo
|
|||
|
||||
if (is_git_repository(filename, &info)) {
|
||||
error = git_save_dives(&info, select_only);
|
||||
cleanup_git_info(&info);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ extern "C" void print_version()
|
|||
|
||||
extern "C" void print_files()
|
||||
{
|
||||
struct git_info info = { };
|
||||
struct git_info info;
|
||||
const char *filename;
|
||||
|
||||
printf("\nFile locations:\n\n");
|
||||
|
@ -58,12 +58,11 @@ extern "C" void print_files()
|
|||
/* strdup so the free below works in either case */
|
||||
filename = strdup("No valid cloud credentials set.\n");
|
||||
}
|
||||
if (info.localdir) {
|
||||
printf("Local git storage: %s\n", info.localdir);
|
||||
if (!info.localdir.empty()) {
|
||||
printf("Local git storage: %s\n", info.localdir.c_str());
|
||||
} else {
|
||||
printf("Unable to get local git directory\n");
|
||||
}
|
||||
cleanup_git_info(&info);
|
||||
printf("Cloud URL: %s\n", filename);
|
||||
free((void *)filename);
|
||||
char *tmp = hashfile_name_string();
|
||||
|
|
|
@ -804,7 +804,7 @@ void QMLManager::loadDivesWithValidCredentials()
|
|||
appendTextToLog("Switching from no cloud mode; keep in memory dive data");
|
||||
}
|
||||
if (info.repo) {
|
||||
appendTextToLog(QString("have repository and branch %1").arg(info.branch));
|
||||
appendTextToLog(QString("have repository and branch %1").arg(info.branch.c_str()));
|
||||
error = git_load_dives(&info, &divelog);
|
||||
} else {
|
||||
appendTextToLog(QString("didn't receive valid git repo, try again"));
|
||||
|
@ -823,7 +823,6 @@ void QMLManager::loadDivesWithValidCredentials()
|
|||
}
|
||||
consumeFinishedLoad();
|
||||
}
|
||||
cleanup_git_info(&info);
|
||||
|
||||
setLoadFromCloud(true);
|
||||
|
||||
|
@ -1501,7 +1500,7 @@ void QMLManager::openNoCloudRepo()
|
|||
appendTextToLog(QString("User asked not to connect to cloud, using %1 as repo.").arg(filename));
|
||||
if (is_git_repository(qPrintable(filename), &info) && !open_git_repository(&info)) {
|
||||
// repo doesn't exist, create it and write the empty dive list to it
|
||||
git_create_local_repo(qPrintable(filename));
|
||||
git_create_local_repo(filename.toStdString());
|
||||
save_dives(qPrintable(filename));
|
||||
existing_filename = filename.toStdString();
|
||||
auto s = qPrefLog::instance();
|
||||
|
@ -1517,7 +1516,7 @@ void QMLManager::saveChangesLocal()
|
|||
if (qPrefCloudStorage::cloud_verification_status() == qPrefCloudStorage::CS_NOCLOUD) {
|
||||
if (existing_filename.empty()) {
|
||||
QString filename = nocloud_localstorage();
|
||||
git_create_local_repo(qPrintable(filename));
|
||||
git_create_local_repo(filename.toStdString());
|
||||
existing_filename = filename.toStdString();
|
||||
auto s = qPrefLog::instance();
|
||||
s->set_default_filename(qPrintable(filename));
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "core/divelist.h"
|
||||
#include "core/divelog.h"
|
||||
#include "core/file.h"
|
||||
#include "core/subsurface-string.h"
|
||||
#include "core/format.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/subsurfacestartup.h"
|
||||
#include "core/settings/qPrefProxy.h"
|
||||
|
@ -23,34 +25,36 @@
|
|||
#endif
|
||||
|
||||
// provide declarations for two local helper functions in git-access.c
|
||||
extern "C" char *get_local_dir(const char *remote, const char *branch);
|
||||
extern "C" void delete_remote_branch(git_repository *repo, const char *remote, const char *branch);
|
||||
std::string get_local_dir(const std::string &remote, const std::string &branch);
|
||||
void delete_remote_branch(git_repository *repo, const std::string &remote, const std::string &branch);
|
||||
|
||||
QString email;
|
||||
QString gitUrl;
|
||||
QString cloudTestRepo;
|
||||
QString localCacheDir;
|
||||
QString localCacheRepo;
|
||||
QString randomBranch;
|
||||
Q_DECLARE_METATYPE(std::string);
|
||||
|
||||
static void moveDir(QString oldName, QString newName)
|
||||
std::string email;
|
||||
std::string gitUrl;
|
||||
std::string cloudTestRepo;
|
||||
std::string localCacheDir;
|
||||
std::string localCacheRepo;
|
||||
std::string randomBranch;
|
||||
|
||||
static void moveDir(const std::string &oldName, const std::string &newName)
|
||||
{
|
||||
QDir oldDir(oldName);
|
||||
QDir newDir(newName);
|
||||
QDir oldDir(oldName.c_str());
|
||||
QDir newDir(newName.c_str());
|
||||
QCOMPARE(newDir.removeRecursively(), true);
|
||||
QCOMPARE(oldDir.rename(oldName, newName), true);
|
||||
QCOMPARE(oldDir.rename(oldName.c_str(), newName.c_str()), true);
|
||||
}
|
||||
|
||||
static void localRemoteCleanup()
|
||||
{
|
||||
// cleanup the local cache dir
|
||||
struct git_info info = { };
|
||||
QDir localCacheDirectory(localCacheDir);
|
||||
struct git_info info;
|
||||
QDir localCacheDirectory(localCacheDir.c_str());
|
||||
QCOMPARE(localCacheDirectory.removeRecursively(), true);
|
||||
|
||||
// when this is first executed, we expect the branch not to exist on the remote server;
|
||||
// if that's true, this will print a harmless error to stderr
|
||||
is_git_repository(qPrintable(cloudTestRepo), &info) && open_git_repository(&info);
|
||||
is_git_repository(cloudTestRepo.c_str(), &info) && open_git_repository(&info);
|
||||
|
||||
// this odd comparison is used to tell that we were able to connect to the remote repo;
|
||||
// in the error case we get the full cloudTestRepo name back as "branch"
|
||||
|
@ -65,8 +69,6 @@ static void localRemoteCleanup()
|
|||
|
||||
// and since this will have created a local repo, remove that one, again so the tests start clean
|
||||
QCOMPARE(localCacheDirectory.removeRecursively(), true);
|
||||
|
||||
cleanup_git_info(&info);
|
||||
}
|
||||
|
||||
void TestGitStorage::initTestCase()
|
||||
|
@ -88,50 +90,50 @@ void TestGitStorage::initTestCase()
|
|||
//
|
||||
// To reduce the risk of collisions on the server, we have ten accounts set up for this purpose
|
||||
// please don't use them for other reasons as they will get deleted regularly
|
||||
email = qgetenv("SSRF_USER_EMAIL");
|
||||
QString password = qgetenv("SSRF_USER_PASSWORD");
|
||||
email = qgetenv("SSRF_USER_EMAIL").toStdString();
|
||||
std::string password(qgetenv("SSRF_USER_PASSWORD").data());
|
||||
|
||||
if (email.isEmpty()) {
|
||||
if (email.empty()) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
email = QString("gitstorage%1@hohndel.org").arg(QRandomGenerator::global()->bounded(10));
|
||||
email = format_string_std("gitstorage%d@hohndel.org", QRandomGenerator::global()->bounded(10));
|
||||
#else
|
||||
// on Qt 5.9 we go back to using qsrand()/qrand()
|
||||
qsrand(time(NULL));
|
||||
email = QString("gitstorage%1@hohndel.org").arg(qrand() % 10);
|
||||
email = format_string_std("gitstorage%d@hohndel.org", qrand() % 10);
|
||||
#endif
|
||||
}
|
||||
if (password.isEmpty())
|
||||
if (password.empty())
|
||||
password = "please-only-use-this-in-the-git-tests";
|
||||
gitUrl = prefs.cloud_base_url;
|
||||
if (gitUrl.right(1) != "/")
|
||||
if (gitUrl.empty() || gitUrl.back() != '/')
|
||||
gitUrl += "/";
|
||||
gitUrl += "git";
|
||||
prefs.cloud_storage_email_encoded = copy_qstring(email);
|
||||
prefs.cloud_storage_password = copy_qstring(password);
|
||||
prefs.cloud_storage_email_encoded = strdup(email.c_str());
|
||||
prefs.cloud_storage_password = strdup(password.c_str());
|
||||
gitUrl += "/" + email;
|
||||
// all user storage for historical reasons always uses the user's email both as
|
||||
// repo name and as branch. To allow us to keep testing and not step on parallel
|
||||
// runs we'll use actually random branch names - yes, this still has a chance of
|
||||
// conflict, but I'm not going to implement a distributed lock manager for this
|
||||
if (email.startsWith("gitstorage")) {
|
||||
if (starts_with(email, "gitstorage")) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
randomBranch = QString::number(QRandomGenerator::global()->bounded(0x1000000), 16) +
|
||||
QString::number(QRandomGenerator::global()->bounded(0x1000000), 16);
|
||||
randomBranch = format_string_std("%x%x", QRandomGenerator::global()->bounded(0x1000000),
|
||||
QRandomGenerator::global()->bounded(0x1000000));
|
||||
#else
|
||||
// on Qt 5.9 we go back to using qsrand()/qrand() -- if we get to this code, qsrand() was already called
|
||||
// even on a 32bit system RAND_MAX is at least 32767 so this will also give us 12 random hex digits
|
||||
randomBranch = QString::number(qrand() % 0x1000, 16) + QString::number(qrand() % 0x1000, 16) +
|
||||
QString::number(qrand() % 0x1000, 16) + QString::number(qrand() % 0x1000, 16);
|
||||
randomBranch = format_string_std("%x%x%x%x", qrand() % 0x1000, qrand() % 0x1000,
|
||||
qrand() % 0x1000, qrand() % 0x1000);
|
||||
#endif
|
||||
} else {
|
||||
// user supplied their own credentials, fall back to the usual "email is branch" pattern
|
||||
randomBranch = email;
|
||||
}
|
||||
cloudTestRepo = gitUrl + QStringLiteral("[%1]").arg(randomBranch);
|
||||
localCacheDir = get_local_dir(qPrintable(gitUrl), qPrintable(randomBranch));
|
||||
localCacheRepo = localCacheDir + QStringLiteral("[%1]").arg(randomBranch);
|
||||
qDebug() << "repo used:" << cloudTestRepo;
|
||||
qDebug() << "local cache:" << localCacheRepo;
|
||||
cloudTestRepo = gitUrl + "[" + randomBranch + ']';
|
||||
localCacheDir = get_local_dir(gitUrl.c_str(), randomBranch.c_str());
|
||||
localCacheRepo = localCacheDir + "[" + randomBranch + "]";
|
||||
qDebug() << "repo used:" << cloudTestRepo.c_str();
|
||||
qDebug() << "local cache:" << localCacheRepo.c_str();
|
||||
|
||||
// make sure we deal with any proxy settings that are needed
|
||||
QNetworkProxy proxy;
|
||||
|
@ -152,7 +154,7 @@ void TestGitStorage::initTestCase()
|
|||
|
||||
// cleanup local and remote branches
|
||||
localRemoteCleanup();
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
}
|
||||
|
||||
void TestGitStorage::cleanupTestCase()
|
||||
|
@ -169,15 +171,16 @@ void TestGitStorage::testGitStorageLocal_data()
|
|||
{
|
||||
// Test different paths we may encounter (since storage depends on user name)
|
||||
// as well as with and without "file://" URL prefix.
|
||||
QTest::addColumn<QString>("testDirName");
|
||||
QTest::addColumn<QString>("prefixRead");
|
||||
QTest::addColumn<QString>("prefixWrite");
|
||||
QTest::newRow("ASCII path") << "./gittest" << "" << "";
|
||||
QTest::newRow("Non ASCII path") << "./gittest_éèêôàüäößíñóúäåöø" << "" << "";
|
||||
QTest::newRow("ASCII path with file:// prefix on read") << "./gittest2" << "file://" << "";
|
||||
QTest::newRow("Non ASCII path with file:// prefix on read") << "./gittest2_éèêôàüäößíñóúäåöø" << "" << "file://";
|
||||
QTest::newRow("ASCII path with file:// prefix on write") << "./gittest3" << "file://" << "";
|
||||
QTest::newRow("Non ASCII path with file:// prefix on write") << "./gittest3_éèêôàüäößíñóúäåöø" << "" << "file://";
|
||||
using namespace std::string_literals; // For std::string literals: "some string"s.
|
||||
QTest::addColumn<std::string>("testDirName");
|
||||
QTest::addColumn<std::string>("prefixRead");
|
||||
QTest::addColumn<std::string>("prefixWrite");
|
||||
QTest::newRow("ASCII path") << "./gittest"s << ""s << ""s;
|
||||
QTest::newRow("Non ASCII path") << "./gittest_éèêôàüäößíñóúäåöø"s << ""s << ""s;
|
||||
QTest::newRow("ASCII path with file:// prefix on read") << "./gittest2"s << "file://"s << ""s;
|
||||
QTest::newRow("Non ASCII path with file:// prefix on read") << "./gittest2_éèêôàüäößíñóúäåöø"s << ""s << "file://"s;
|
||||
QTest::newRow("ASCII path with file:// prefix on write") << "./gittest3"s << "file://"s << ""s;
|
||||
QTest::newRow("Non ASCII path with file:// prefix on write") << "./gittest3_éèêôàüäößíñóúäåöø"s << ""s << "file://"s;
|
||||
}
|
||||
|
||||
void TestGitStorage::testGitStorageLocal()
|
||||
|
@ -185,19 +188,19 @@ void TestGitStorage::testGitStorageLocal()
|
|||
// test writing and reading back from local git storage
|
||||
git_repository *repo;
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/SampleDivesV2.ssrf", &divelog), 0);
|
||||
QFETCH(QString, testDirName);
|
||||
QFETCH(QString, prefixRead);
|
||||
QFETCH(QString, prefixWrite);
|
||||
QDir testDir(testDirName);
|
||||
QFETCH(std::string, testDirName);
|
||||
QFETCH(std::string, prefixRead);
|
||||
QFETCH(std::string, prefixWrite);
|
||||
QDir testDir(testDirName.c_str());
|
||||
QCOMPARE(testDir.removeRecursively(), true);
|
||||
QCOMPARE(QDir().mkdir(testDirName), true);
|
||||
QString repoNameRead = prefixRead + testDirName;
|
||||
QString repoNameWrite = prefixWrite + testDirName;
|
||||
QCOMPARE(git_repository_init(&repo, qPrintable(testDirName), false), 0);
|
||||
QCOMPARE(save_dives(qPrintable(repoNameWrite + "[test]")), 0);
|
||||
QCOMPARE(QDir().mkdir(testDirName.c_str()), true);
|
||||
std::string repoNameRead = prefixRead + testDirName;
|
||||
std::string repoNameWrite = prefixWrite + testDirName;
|
||||
QCOMPARE(git_repository_init(&repo, testDirName.c_str(), false), 0);
|
||||
QCOMPARE(save_dives((repoNameWrite + "[test]").c_str()), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3.ssrf"), 0);
|
||||
clear_dive_file_data();
|
||||
QCOMPARE(parse_file(qPrintable(repoNameRead + "[test]"), &divelog), 0);
|
||||
QCOMPARE(parse_file((repoNameRead + "[test]").c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3viagit.ssrf"), 0);
|
||||
QFile org("./SampleDivesV3.ssrf");
|
||||
org.open(QFile::ReadOnly);
|
||||
|
@ -216,9 +219,9 @@ void TestGitStorage::testGitStorageCloud()
|
|||
// connect to the ssrftest repository on the cloud server
|
||||
// and repeat the same test as before with the local git storage
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/SampleDivesV2.ssrf", &divelog), 0);
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3viacloud.ssrf"), 0);
|
||||
QFile org("./SampleDivesV3.ssrf");
|
||||
org.open(QFile::ReadOnly);
|
||||
|
@ -236,19 +239,19 @@ void TestGitStorage::testGitStorageCloudOfflineSync()
|
|||
// make a change to local cache repo (pretending that we did some offline changes)
|
||||
// and then open the remote one again and check that things were propagated correctly
|
||||
// read the local repo from the previous test and add dive 10
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test10.xml", &divelog), 0);
|
||||
// calling process_loaded_dives() sorts the table, but calling add_imported_dives()
|
||||
// causes it to try to update the window title... let's not do that
|
||||
process_loaded_dives();
|
||||
// now save only to the local cache but not to the remote server
|
||||
git_local_only = true;
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3plus10local.ssrf"), 0);
|
||||
clear_dive_file_data();
|
||||
// now pretend that we are online again and open the cloud storage and compare
|
||||
git_local_only = false;
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3plus10viacloud.ssrf"), 0);
|
||||
QFile org("./SampleDivesV3plus10local.ssrf");
|
||||
org.open(QFile::ReadOnly);
|
||||
|
@ -260,10 +263,10 @@ void TestGitStorage::testGitStorageCloudOfflineSync()
|
|||
QString written = outS.readAll();
|
||||
QCOMPARE(readin, written);
|
||||
// write back out to cloud storage, move away the local cache, open again and compare
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
moveDir(localCacheDir, localCacheDir + "save");
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesV3plus10fromcloud.ssrf"), 0);
|
||||
org.close();
|
||||
org.open(QFile::ReadOnly);
|
||||
|
@ -292,10 +295,10 @@ void TestGitStorage::testGitStorageCloudMerge()
|
|||
|
||||
// (1) open the repo, add dive test11 and save to the cloud
|
||||
git_local_only = false;
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test11.xml", &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (2) switch to the second client by moving the old cache back in place
|
||||
|
@ -304,15 +307,15 @@ void TestGitStorage::testGitStorageCloudMerge()
|
|||
|
||||
// (3) open the repo from the old cache and add dive test12 while offline
|
||||
git_local_only = true;
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(parse_file(SUBSURFACE_TEST_DATA "/dives/test12.xml", &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (4) now take things back online
|
||||
git_local_only = false;
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (5) now we should have all the dives in our repo on the second client
|
||||
|
@ -324,7 +327,7 @@ void TestGitStorage::testGitStorageCloudMerge()
|
|||
QCOMPARE(save_dives("./SampleDivesV3plus10-11-12.ssrf"), 0);
|
||||
// then load from the cloud
|
||||
clear_dive_file_data();
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QCOMPARE(save_dives("./SampleDivesV3plus10-11-12-merged.ssrf"), 0);
|
||||
// finally compare what we have
|
||||
|
@ -341,7 +344,7 @@ void TestGitStorage::testGitStorageCloudMerge()
|
|||
|
||||
// (6) move ourselves back to the first client and compare data there
|
||||
moveDir(localCacheDir + "client1", localCacheDir);
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QCOMPARE(save_dives("./SampleDivesV3plus10-11-12-merged-client1.ssrf"), 0);
|
||||
QFile client1("./SampleDivesV3plus10-11-12-merged-client1.ssrf");
|
||||
|
@ -357,13 +360,13 @@ void TestGitStorage::testGitStorageCloudMerge2()
|
|||
// edit the same dive in the cloud repo
|
||||
// merge
|
||||
// (1) open repo, delete second dive, save offline
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
struct dive *dive = get_dive(1);
|
||||
delete_single_dive(1);
|
||||
QCOMPARE(save_dives("./SampleDivesMinus1.ssrf"), 0);
|
||||
git_local_only = true;
|
||||
QCOMPARE(save_dives(qPrintable(localCacheRepo)), 0);
|
||||
QCOMPARE(save_dives(localCacheRepo.c_str()), 0);
|
||||
git_local_only = false;
|
||||
clear_dive_file_data();
|
||||
|
||||
|
@ -371,21 +374,21 @@ void TestGitStorage::testGitStorageCloudMerge2()
|
|||
moveDir(localCacheDir, localCacheDir + "save");
|
||||
|
||||
// (3) now we open the cloud storage repo and modify that second dive
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
dive = get_dive(1);
|
||||
QVERIFY(dive != NULL);
|
||||
free(dive->notes);
|
||||
dive->notes = strdup("These notes have been modified by TestGitStorage");
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (4) move the saved local cache backinto place and try to open the cloud repo
|
||||
// -> this forces a merge
|
||||
moveDir(localCacheDir + "save", localCacheDir);
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesMinus1-merged.ssrf"), 0);
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
QFile org("./SampleDivesMinus1-merged.ssrf");
|
||||
org.open(QFile::ReadOnly);
|
||||
QFile out("./SampleDivesMinus1.ssrf");
|
||||
|
@ -406,7 +409,7 @@ void TestGitStorage::testGitStorageCloudMerge3()
|
|||
|
||||
|
||||
// (1) open repo, edit notes of first three dives
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
struct dive *dive;
|
||||
QVERIFY((dive = get_dive(0)) != 0);
|
||||
|
@ -418,11 +421,11 @@ void TestGitStorage::testGitStorageCloudMerge3()
|
|||
QVERIFY((dive = get_dive(2)) != 0);
|
||||
free(dive->notes);
|
||||
dive->notes = strdup("Create multi line dive notes\nLine 2\nLine 3\nLine 4\nLine 5\nThat should be enough");
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (2) make different edits offline
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QVERIFY((dive = get_dive(0)) != 0);
|
||||
free(dive->notes);
|
||||
|
@ -434,14 +437,14 @@ void TestGitStorage::testGitStorageCloudMerge3()
|
|||
free(dive->notes);
|
||||
dive->notes = strdup("single line dive notes");
|
||||
git_local_only = true;
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
git_local_only = false;
|
||||
clear_dive_file_data();
|
||||
|
||||
// (3) simulate a second system by moving the cache away and open the cloud storage repo and modify
|
||||
// those first dive notes differently while online
|
||||
moveDir(localCacheDir, localCacheDir + "save");
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
process_loaded_dives();
|
||||
QVERIFY((dive = get_dive(0)) != 0);
|
||||
free(dive->notes);
|
||||
|
@ -452,12 +455,12 @@ void TestGitStorage::testGitStorageCloudMerge3()
|
|||
QVERIFY((dive = get_dive(2)) != 0);
|
||||
free(dive->notes);
|
||||
dive->notes = strdup("Line 2\nLine 3\nLine 4\nLine 5"); // keep the middle, remove first and last");
|
||||
QCOMPARE(save_dives(qPrintable(cloudTestRepo)), 0);
|
||||
QCOMPARE(save_dives(cloudTestRepo.c_str()), 0);
|
||||
clear_dive_file_data();
|
||||
|
||||
// (4) move the saved local cache back into place and open the cloud repo -> this forces a merge
|
||||
moveDir(localCacheDir + "save", localCacheDir);
|
||||
QCOMPARE(parse_file(qPrintable(cloudTestRepo), &divelog), 0);
|
||||
QCOMPARE(parse_file(cloudTestRepo.c_str(), &divelog), 0);
|
||||
QCOMPARE(save_dives("./SampleDivesMerge3.ssrf"), 0);
|
||||
// we are not trying to compare this to a pre-determined result... what this test
|
||||
// checks is that there are no parsing errors with the merge
|
||||
|
|
|
@ -42,8 +42,8 @@ void TestParsePerformance::initTestCase()
|
|||
QNetworkProxy::setApplicationProxy(proxy);
|
||||
|
||||
// now cleanup the cache dir in case there's something weird from previous runs
|
||||
QString localCacheDir(get_local_dir(LARGE_TEST_REPO, "git"));
|
||||
QDir localCacheDirectory(localCacheDir);
|
||||
std::string localCacheDir = get_local_dir(LARGE_TEST_REPO, "git");
|
||||
QDir localCacheDirectory(localCacheDir.c_str());
|
||||
QCOMPARE(localCacheDirectory.removeRecursively(), true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue