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

Trustful IPFS Store #3727

Draft
wants to merge 163 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
e2bedd2
libstore: add basic IPFS binary cache support
mguentner Jan 28, 2017
fb47242
src/libmain/stack.cc: fix 'ucontext' usage on glibc-2.26
Aug 31, 2017
8406fdf
Merge commit 'c9857ef262c391672b47e7714e61f1686b684e4d' into old-ipfs…
Ericson2314 Jun 5, 2020
9c1d129
Merge commit '5449ff7d8aaa8dce6d6f7e47c89e04d914f16cff' into old-ipfs…
Ericson2314 Jun 5, 2020
62b6cb9
Update the ipfs binary store code
meditans Jun 8, 2020
8e70444
Merge remote-tracking branch 'upstream/master' into old-ipfs_binary_c…
Ericson2314 Jun 8, 2020
aa2b8f0
Support POST in file transfer
matthewbauer Jun 9, 2020
f7f27a2
Support data with POST in file transfer
matthewbauer Jun 9, 2020
aa0e736
Consolidate ipfs-binary-cache-store.cc to one file
matthewbauer Jun 9, 2020
adec10c
Use /api/v0/version to check if ipfs daemon is running
matthewbauer Jun 9, 2020
e39ce69
Throw error if /ipfs/ is used but path doesn’t exist
matthewbauer Jun 9, 2020
f33f8e6
Support uploading with /ipns/ in ipfs-binary-cache-store
matthewbauer Jun 9, 2020
37393d1
Create file if nix-cache-info doesn’t exist
matthewbauer Jun 9, 2020
a9343ed
Use POST for IPFS getFile
matthewbauer Jun 10, 2020
ab712b4
Ignore 500 errors in ipfs binary cache
matthewbauer Jun 10, 2020
3530ab1
Use offline to speed up IPFS publish
matthewbauer Jun 10, 2020
c135e05
Keep track of in progress upsert
matthewbauer Jun 10, 2020
6be117f
Use addrType enum in IPFSBinaryCacheStore
matthewbauer Jun 10, 2020
b62782d
Cleanup
matthewbauer Jun 10, 2020
bc012e5
Add sync() to store API
matthewbauer Jun 10, 2020
168cb9e
Fixup fileExists method in IPFSBinaryCacheStore
matthewbauer Jun 10, 2020
4b24d04
Temporarily reduce CI platform's for sake of Obsidian's own CI
Ericson2314 Jun 1, 2020
816ff04
Store IPFS path in state
matthewbauer Jun 10, 2020
904ab3c
Merge remote-tracking branch 'obsidian/ipfs-binary-cache-develop' int…
Ericson2314 Jun 11, 2020
a09c57e
Merge remote-tracking branch 'obsidian/ipfs-binary-cache-with-upload'…
Ericson2314 Jun 11, 2020
03a90fc
ipnsPath -> optIpnsPath
Ericson2314 Jun 11, 2020
25c5ced
Avoid too many `optIpnsPath`
Ericson2314 Jun 11, 2020
e899575
Merge pull request #11 from obsidiansystems/ipfs-binary-cache-with-up…
Ericson2314 Jun 11, 2020
1f88199
WIP test suite automatization
meditans Jun 11, 2020
efd8790
Merge pull request #10 from obsidiansystems/ipfs-binary-cache-with-up…
Ericson2314 Jun 11, 2020
33c6149
With a derivation that doesn't use nixpkgs
meditans Jun 11, 2020
25f71d3
need to run init.sh first, sigh
Ericson2314 Jun 11, 2020
8a3c073
Complete the tests for ipfs
meditans Jun 11, 2020
682b936
Merge branch 'ipfs-binary-cache-develop' of github.com:obsidiansystem…
meditans Jun 11, 2020
0da205b
Update prefixes for ipfs and ipns in test suite
meditans Jun 11, 2020
753ed62
Add ipfs as a dep for tests
Ericson2314 Jun 11, 2020
4750223
Restart ipfs when the daemon is not running
meditans Jun 11, 2020
b2eccb9
Sometimes read permissions dissapear on the test data for some reason
Ericson2314 Jun 12, 2020
0068f7d
Ensure IPFS daemon is killed after test
Ericson2314 Jun 12, 2020
5352bcb
Just run ipfs tests on linux for now, sigh
Ericson2314 Jun 12, 2020
7599cf0
Fix syntax error from bad paste
Ericson2314 Jun 12, 2020
4348615
Remove `NIX_REMOTE=local` from ipfs test
Ericson2314 Jun 12, 2020
67c63b9
Only call build once in tests/ipfs.sh
matthewbauer Jun 12, 2020
e1d0091
Clear store when beginning ipfs test
matthewbauer Jun 12, 2020
4f3a4c9
Fix typo in ipfs.sh
matthewbauer Jun 12, 2020
4b83835
Fixup unset BUILD_COMMAND
matthewbauer Jun 12, 2020
3cb4a0b
Try to make /nar before nix copy in tests/ipfs.sh
matthewbauer Jun 13, 2020
ad96d21
Revert "Just run ipfs tests on linux for now, sigh"
Ericson2314 Jun 13, 2020
08ee366
ipfs test: Inline some vars used once
Ericson2314 Jun 13, 2020
953ceba
Identify real issue (#3695) and hack around it
Ericson2314 Jun 13, 2020
913d1c5
Merge pull request #12 from obsidiansystems/cn-test-suite-automatization
Ericson2314 Jun 13, 2020
77d27f0
Check that ipfs and ipns hashes correspond
meditans Jun 15, 2020
caf4db0
Add initialIpfsPath and refine sync checks
meditans Jun 15, 2020
6f01ad8
Deal with non happy paths first
meditans Jun 15, 2020
c33307e
Correct condition
meditans Jun 15, 2020
5125a7c
Better error message
meditans Jun 15, 2020
16ecf60
Better logic
meditans Jun 15, 2020
3561945
Return the domain in isDNSLinkPath
meditans Jun 15, 2020
7075697
Merge pull request #13 from obsidiansystems/cn-resolve-and-check-ipns…
Ericson2314 Jun 15, 2020
f1d6066
Move ipfs-specific method to own functions
matthewbauer Jun 15, 2020
4ca9724
Correctly specify visibility of ipfs-binary-cache-store
matthewbauer Jun 15, 2020
784e786
Add ipfsObjectExists
matthewbauer Jun 15, 2020
ca1a565
Fixup ipfs-binary-cache-store modifiers
matthewbauer Jun 15, 2020
12f4035
Merge remote-tracking branch 'upstream/master' into old-ipfs_binary_c…
Ericson2314 Jun 15, 2020
560f9f1
Merge branch 'old-ipfs_binary_cache' into ipfs-binary-cache-develop
Ericson2314 Jun 15, 2020
b5b84dd
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Jun 16, 2020
d939738
Get and use proper key for uploading from the hash
meditans Jun 16, 2020
054cabf
Add dag helper methods
matthewbauer Jun 15, 2020
9606d96
Merge remote-tracking branch 'obsidian/fix-include' into ipfs-binary-…
Ericson2314 Jun 16, 2020
df3aea2
Implement Store directly instead of via BinaryCacheStore
matthewbauer Jun 16, 2020
213ded3
Remove offline from publish
matthewbauer Jun 16, 2020
93d71ae
Use IPLD instead of UnixFS
matthewbauer Jun 16, 2020
d1fc077
Make error message more idiomatic
matthewbauer Jun 16, 2020
afb080b
Merge remote-tracking branch 'obsidian/ipfs-binary-cache-develop' int…
Ericson2314 Jun 17, 2020
5bebd3a
Merge branch 'master' of github.com:NixOS/nix into ipfs-binary-cache-…
Ericson2314 Jun 17, 2020
ee24a54
Merge pull request #16 from obsidiansystems/ipfs-binary-cache-new-master
Ericson2314 Jun 17, 2020
9408826
Merge remote-tracking branch 'obsidian/ipfs-binary-cache-develop' int…
Ericson2314 Jun 17, 2020
7fa8391
Properly store compression / system in ipfs binary cache
matthewbauer Jun 17, 2020
00e351b
Add direct uploading to ipfs and ipns
meditans Jun 17, 2020
90c5199
Add possibility of pushing directly to ipfs
meditans Jun 17, 2020
f64fe0b
Merge branch 'ipfs-binary-cache-develop' of github.com:obsidiansystem…
meditans Jun 17, 2020
23347cb
Move compareVersions to libutil
matthewbauer Jun 17, 2020
38ef66d
Add check to make sure ipfs daemon is 0.4.0
matthewbauer Jun 17, 2020
fadc5bf
Publish the empty-dir to ipns to get the hash
meditans Jun 17, 2020
101e718
Throw error if keyName is not found
meditans Jun 17, 2020
5caf620
Increment CURLOPT_EXPECT_100_TIMEOUT_MS to 5 min
matthewbauer Jun 17, 2020
2ffe057
Merge remote-tracking branch 'obsidiansystems/ipfs-binary-cache-devel…
matthewbauer Jun 17, 2020
dc8557c
Merge pull request #18 from obsidiansystems/ipfs-binary-cache-version…
Ericson2314 Jun 17, 2020
96e2ebd
Add ipnsPath to mismatch error
matthewbauer Jun 17, 2020
e54f5bf
Try using e.info() instead of e.msg()
matthewbauer Jun 18, 2020
77d2c5c
Merge remote-tracking branch 'obsidian/fix-url-format' into cn-fix-ip…
Ericson2314 Jun 18, 2020
ae33ef1
Merge branch 'add-body-to-network-errors' into cn-fix-ipns-upload
Ericson2314 Jun 18, 2020
46701e0
Also allow for offline use
meditans Jun 18, 2020
0bf5d1d
Merge branch 'cn-fix-ipns-upload' of github.com:obsidiansystems/nix i…
Ericson2314 Jun 18, 2020
2c89c62
Set allow-offline=true on publish
matthewbauer Jun 18, 2020
a748970
Merge pull request #17 from obsidiansystems/cn-fix-ipns-upload
Ericson2314 Jun 18, 2020
e9d538e
Simplify loop
meditans Jun 18, 2020
f70023a
Merge remote-tracking branch 'obsidiansystems/cn-fix-ipns-upload' int…
matthewbauer Jun 18, 2020
ed0e05d
Add note regarding key lookup
matthewbauer Jun 18, 2020
81abf59
Verify a derivation with dependencies works in ipfs
matthewbauer Jun 18, 2020
9da7b5b
Merge remote-tracking branch 'obsidiansystems/ipfs-binary-cache-devel…
matthewbauer Jun 18, 2020
d360846
Revert "Move compareVersions to libutil"
matthewbauer Jun 18, 2020
cf0fbca
Merge pull request #19 from obsidiansystems/ipfs-add-body-to-network-…
Ericson2314 Jun 18, 2020
b7e39e0
Merge pull request #21 from obsidiansystems/undo-compareVersions-split
Ericson2314 Jun 18, 2020
c84a956
Merge pull request #20 from obsidiansystems/cn-fixup-simplify-loop
Ericson2314 Jun 18, 2020
ba7a4b7
Readd ipfs gateway tests
matthewbauer Jun 18, 2020
9e4268d
Add FIXME for CURLOPT_EXPECT_100_TIMEOUT_MS
matthewbauer Jun 18, 2020
61997ab
Merge remote-tracking branch 'obsidiansystems/ipfs-binary-cache-devel…
matthewbauer Jun 18, 2020
4b11fbd
Merge pull request #15 from obsidiansystems/ipfs-binary-cache-ipld
Ericson2314 Jun 18, 2020
96e642b
Don’t include storeDir in ipfs dictionary
matthewbauer Jun 19, 2020
90535e8
Always include empty fields in ipfs json
matthewbauer Jun 19, 2020
7b90966
Merge pull request #22 from obsidiansystems/ipfs-binary-cache-ipld-fix
Ericson2314 Jun 19, 2020
a702f9a
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Jun 19, 2020
e05276a
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Jun 22, 2020
dba20fa
Allow blank CA field in IPFS store to indicate not content addressed
Ericson2314 Jun 22, 2020
ec61165
Structure content addresses in IPFS store
Ericson2314 Jun 22, 2020
97b8649
Rename local variable `hash` -> `hashAlgo`
Ericson2314 Jun 22, 2020
81f2058
Merge pull request #24 from obsidiansystems/json-ca
Ericson2314 Jun 22, 2020
13512c1
`nlohmann_json` is now used in a header used by the perl bindings
Ericson2314 Jun 22, 2020
31f6ca8
Merge remote-tracking branch 'obsidian/add-body-to-network-errors' in…
Ericson2314 Jun 22, 2020
8d1e710
Create permentant IPFS roots for `addTempRoot`
Ericson2314 Jun 22, 2020
6a779a5
Better error for ipfs address mismatch
meditans Jun 23, 2020
c354ba6
Fix the tests
meditans Jun 23, 2020
a02c2a5
Merge pull request #28 from obsidiansystems/better-error-for-ipfs-add…
Ericson2314 Jun 23, 2020
d8bd3cf
Clean up grepping for right ipfs address in tests
meditans Jun 23, 2020
96a256d
Merge pull request #29 from obsidiansystems/better-grepping-for-corre…
Ericson2314 Jun 23, 2020
e7e71df
Merge branch 'ipfs-binary-cache-develop' into ipfs-not-so-temp-root
Ericson2314 Jun 23, 2020
0a9f1a5
Fix pin relative path
Ericson2314 Jun 23, 2020
7477c77
Use adjacent string literals to better show intent
Ericson2314 Jun 23, 2020
2fa8676
Add test case for this
meditans Jun 24, 2020
1d7ceb0
Add sync and correct hash conditions
meditans Jun 24, 2020
bd8b3eb
Merge pull request #26 from obsidiansystems/ipfs-not-so-temp-root
Ericson2314 Jun 25, 2020
64b25a6
Add jq as test dep
Ericson2314 Jun 30, 2020
bcd293e
Sync stores at the end of commands, not within
Ericson2314 Jun 30, 2020
0838c21
Add Store::sync to daemon protocol
Ericson2314 Jun 30, 2020
6cc4277
Merge pull request #38 from obsidiansystems/raii-sync
Ericson2314 Jun 30, 2020
0bd0623
Merge pull request #39 from obsidiansystems/daemon-op-sync
Ericson2314 Jun 30, 2020
6d0a565
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Jul 2, 2020
58c772d
IPFS tests: more no out-link
Ericson2314 Jul 3, 2020
e997a76
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Jul 3, 2020
222703d
Improve IPFS error messages
Ericson2314 Jul 6, 2020
f287338
Merge pull request #45 from obsidiansystems/ipfs-error-msg
Ericson2314 Jul 6, 2020
bd00f74
Create header for ipfs-binary-cache-store
meditans Jul 7, 2020
9e836a2
Merge pull request #49 from obsidiansystems/create-header-ipfs-binary…
Ericson2314 Jul 7, 2020
1eb8ac7
Fix include directives for ipfs binary cache store
meditans Jul 7, 2020
06d59df
Merge pull request #50 from obsidiansystems/fix-includes-for-ipfs-bin…
Ericson2314 Jul 7, 2020
dcff86c
Merge branch 'add-body-to-network-errors' of github.com:obsidiansyste…
meditans Jul 15, 2020
f618957
Add todo for better error wrapping
meditans Jul 15, 2020
c4a0574
Merge pull request #64 from obsidiansystems/ipfs-binary-cache-develop…
Ericson2314 Jul 15, 2020
fa5ffd0
Add allow-modify flag to cache
matthewbauer Jul 10, 2020
9d223c1
Change to assertion, better errors, new test
meditans Jul 13, 2020
2ef8338
Merge pull request #65 from obsidiansystems/ipfs-binary-cache-develop…
Ericson2314 Jul 15, 2020
f206449
Merge branch 'master' of github.com:NixOS/nix into ipfs-binary-cache-…
Ericson2314 Jul 21, 2020
1c8b979
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Aug 3, 2020
af04f49
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Aug 7, 2020
8066237
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Sep 16, 2020
1d3c6ae
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Sep 22, 2020
cde9c15
WIP: Get IPFS store working with StoreConfig refactor
Ericson2314 Sep 22, 2020
c3f3452
Merge pull request #78 from obsidiansystems/ipfs-mini-store-config-merge
Ericson2314 Sep 23, 2020
0ba15e5
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Sep 23, 2020
d868b58
Fix IPFS store constructors
Ericson2314 Sep 23, 2020
b3008a2
Improve IPFS test a bit
Ericson2314 Sep 23, 2020
9726978
Merge remote-tracking branch 'upstream/master' into ipfs-binary-cache…
Ericson2314 Oct 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@
(aws-sdk-cpp.override {
apis = ["s3" "transfer"];
customMemoryManagement = false;
});
})
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) ipfs;

propagatedDeps =
[ (boehmgc.override { enableLargeConfig = true; })
Expand Down
60 changes: 60 additions & 0 deletions src/libstore/content-address.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <nlohmann/json.hpp>

#include "args.hh"
#include "content-address.hh"
#include "split.hh"
Expand Down Expand Up @@ -134,6 +136,64 @@ std::string renderContentAddress(std::optional<ContentAddress> ca)
return ca ? renderContentAddress(*ca) : "";
}

void to_json(nlohmann::json& j, const ContentAddress & ca) {
j = std::visit(overloaded {
[](TextHash th) {
return nlohmann::json {
{ "type", "text" },
{ "hash", th.hash.to_string(Base32, false) },
};
},
[](FixedOutputHash foh) {
return nlohmann::json {
{ "type", "fixed" },
{ "method", foh.method == FileIngestionMethod::Flat ? "flat" : "recursive" },
{ "algo", printHashType(foh.hash.type) },
{ "hash", foh.hash.to_string(Base32, false) },
};
}
}, ca);
}

void from_json(const nlohmann::json& j, ContentAddress & ca) {
std::string_view type = j.at("type").get<std::string_view>();
if (type == "text") {
ca = TextHash {
.hash = Hash::parseNonSRIUnprefixed(j.at("hash").get<std::string_view>(), htSHA256),
};
} else if (type == "fixed") {
std::string_view methodRaw = j.at("method").get<std::string_view>();
auto method = methodRaw == "flat" ? FileIngestionMethod::Flat
: methodRaw == "recursive" ? FileIngestionMethod::Recursive
: throw Error("invalid file ingestion method: %s", methodRaw);
auto hashAlgo = parseHashType(j.at("algo").get<std::string>());
ca = FixedOutputHash {
.method = method,
.hash = Hash::parseNonSRIUnprefixed(j.at("hash").get<std::string_view>(), hashAlgo),
};
} else
throw Error("invalid type: %s", type);
}

// Needed until https://github.com/nlohmann/json/pull/2117

void to_json(nlohmann::json& j, const std::optional<ContentAddress> & c) {
if (!c)
j = nullptr;
else
to_json(j, *c);
}

void from_json(const nlohmann::json& j, std::optional<ContentAddress> & c) {
if (j.is_null()) {
c = std::nullopt;
} else {
// Dummy value to set tag bit.
c = TextHash { .hash = Hash { htSHA256 } };
from_json(j, *c);
}
}

Hash getContentAddressHash(const ContentAddress & ca)
{
return std::visit(overloaded {
Expand Down
9 changes: 9 additions & 0 deletions src/libstore/content-address.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <nlohmann/json.hpp>
#include <variant>

#include "hash.hh"

namespace nix {
Expand Down Expand Up @@ -53,6 +55,13 @@ ContentAddress parseContentAddress(std::string_view rawCa);

std::optional<ContentAddress> parseContentAddressOpt(std::string_view rawCaOpt);

void to_json(nlohmann::json& j, const ContentAddress & c);
void from_json(const nlohmann::json& j, ContentAddress & c);

// Needed until https://github.com/nlohmann/json/pull/211

void to_json(nlohmann::json& j, const std::optional<ContentAddress> & c);
void from_json(const nlohmann::json& j, std::optional<ContentAddress> & c);
Hash getContentAddressHash(const ContentAddress & ca);

/*
Expand Down
8 changes: 8 additions & 0 deletions src/libstore/daemon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,14 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
break;
}

case wopSync: {
logger->startWork();
store->sync();
logger->stopWork();
to << 1;
break;
}

default:
throw Error("invalid operation %1%", op);
}
Expand Down
48 changes: 44 additions & 4 deletions src/libstore/filetransfer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ FileTransferSettings fileTransferSettings;

static GlobalConfig::Register rFileTransferSettings(&fileTransferSettings);

MakeError(URLEncodeError, Error);

std::string resolveUri(const std::string & uri)
{
if (uri.compare(0, 8, "channel:") == 0)
Expand Down Expand Up @@ -310,12 +312,22 @@ struct curlFileTransfer : public FileTransfer

if (request.head)
curl_easy_setopt(req, CURLOPT_NOBODY, 1);
else if (request.post)
curl_easy_setopt(req, CURLOPT_POST, 1);

if (request.data) {
curl_easy_setopt(req, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(req, CURLOPT_READFUNCTION, readCallbackWrapper);
curl_easy_setopt(req, CURLOPT_READDATA, this);
curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->length());
if (request.post) {
// based off of https://curl.haxx.se/libcurl/c/postit2.html
curl_mime *form = curl_mime_init(req);
curl_mimepart *field = curl_mime_addpart(form);
curl_mime_data(field, request.data->data(), request.data->length());
curl_easy_setopt(req, CURLOPT_MIMEPOST, form);
} else {
curl_easy_setopt(req, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(req, CURLOPT_READFUNCTION, readCallbackWrapper);
curl_easy_setopt(req, CURLOPT_READDATA, this);
curl_easy_setopt(req, CURLOPT_INFILESIZE_LARGE, (curl_off_t) request.data->length());
}
}

if (request.verifyTLS) {
Expand All @@ -332,6 +344,14 @@ struct curlFileTransfer : public FileTransfer
curl_easy_setopt(req, CURLOPT_LOW_SPEED_LIMIT, 1L);
curl_easy_setopt(req, CURLOPT_LOW_SPEED_TIME, fileTransferSettings.stalledDownloadTimeout.get());

/* FIXME: We hit a weird issue when 1 second goes by
* without Expect: 100-continue. curl_multi_perform
* appears to block indefinitely. To workaround this, we
* just set the timeout to a really big value unlikely to
* be hit in any server without Expect: 100-continue. This
* may specifically be a bug in the IPFS API. */
curl_easy_setopt(req, CURLOPT_EXPECT_100_TIMEOUT_MS, 300000);

/* If no file exist in the specified path, curl continues to work
anyway as if netrc support was disabled. */
curl_easy_setopt(req, CURLOPT_NETRC_FILE, settings.netrcFile.get().c_str());
Expand Down Expand Up @@ -711,6 +731,22 @@ struct curlFileTransfer : public FileTransfer

enqueueItem(std::make_shared<TransferItem>(*this, request, std::move(callback)));
}

std::string urlEncode(const std::string & param) override {
//TODO reuse curl handle or move function to another class/file
CURL *curl = curl_easy_init();
char *encoded = NULL;
if (curl) {
encoded = curl_easy_escape(curl, param.c_str(), 0);
}
if ((curl == NULL) || (encoded == NULL)) {
throw URLEncodeError("Could not encode param");
}
std::string ret(encoded);
curl_free(encoded);
curl_easy_cleanup(curl);
return ret;
}
};

ref<FileTransfer> getFileTransfer()
Expand Down Expand Up @@ -844,6 +880,10 @@ void FileTransfer::download(FileTransferRequest && request, Sink & sink)
}
}

std::string FileTransfer::urlEncode(const std::string & param) {
throw URLEncodeError("not implemented");
}

template<typename... Args>
FileTransferError::FileTransferError(FileTransfer::Error error, std::shared_ptr<string> response, const Args & ... args)
: Error(args...), error(error), response(response)
Expand Down
3 changes: 3 additions & 0 deletions src/libstore/filetransfer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct FileTransferRequest
std::string expectedETag;
bool verifyTLS = true;
bool head = false;
bool post = false;
size_t tries = fileTransferSettings.tries;
unsigned int baseRetryTimeMs = 250;
ActivityId parentAct;
Expand Down Expand Up @@ -105,6 +106,8 @@ struct FileTransfer
invoked on the thread of the caller. */
void download(FileTransferRequest && request, Sink & sink);

virtual std::string urlEncode(const std::string & param);

enum Error { NotFound, Forbidden, Misc, Transient, Interrupted };
};

Expand Down
Loading