Skip to content

Commit fd90a85

Browse files
committed
Update:
- Windows is now using winhttp for downloading thus not requiring libcurl. - Updated sdlite dependency - Added missing help info for redub use and install
1 parent f9e9004 commit fd90a85

File tree

17 files changed

+253
-34
lines changed

17 files changed

+253
-34
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Redub - Dub Based Build System
2+
[![Update release and nightly](https://github.com/MrcSnm/redub/actions/workflows/ci.yml/badge.svg)](https://github.com/MrcSnm/redub/actions/workflows/ci.yml)
23

34

45
## Running redub without having it on path

d_downloader/.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
*.exe
2+
*.pdb
3+
*.o
4+
*.obj
5+
*.lst
6+
*.lnk
7+
.history
8+
.dub
9+
docs.json
10+
__dummy.html
11+
docs/
12+
/d_downloader
13+
d_downloader.so
14+
d_downloader.dylib
15+
d_downloader.dll
16+
d_downloader.a
17+
d_downloader.lib
18+
d_downloader-test-*

d_downloader/dub.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"authors": [
3+
"Marcelo"
4+
],
5+
"configurations": [
6+
{
7+
"name": "winhttp",
8+
"platforms": ["windows"],
9+
"libs": ["winhttp"]
10+
},
11+
{
12+
"name": "curl"
13+
}
14+
],
15+
"description": "A downloader library which avoids using libcurl so Windows do not needs to link, while use libcurls on other platforms",
16+
"license": "proprietary",
17+
"name": "d_downloader"
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module d_downloader.curl;
2+
version(Posix):
3+
import std.net.curl;
4+
ubyte[] downloadToBuffer(string file)
5+
{
6+
HTTP http = HTTP(file);
7+
ubyte[] temp;
8+
http.onReceive = (ubyte[] data)
9+
{
10+
temp~= data;
11+
return data.length;
12+
};
13+
http.perform();
14+
return temp;
15+
}
16+
alias downloadToFile = std.net.curl.download;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module d_downloader;
2+
version(Windows)
3+
public import d_downloader.windows;
4+
else
5+
public import d_downloader.curl;
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
module d_downloader.windows;
2+
version(Windows):
3+
import core.sys.windows.winhttp;
4+
5+
bool download(string link, scope ubyte[] delegate(size_t incomingBytes) bufferSink, scope void delegate(ubyte[] buffer) onDataReceived = null)
6+
{
7+
import std.utf:toUTF16z;
8+
import core.sys.windows.windef;
9+
HINTERNET hSession = WinHttpOpen("D-Downloader/1.0",
10+
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
11+
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
12+
13+
if (!hSession)
14+
return false;
15+
scope(exit)
16+
WinHttpCloseHandle(hSession);
17+
18+
NetURL url = NetURL(link);
19+
20+
uint[1] protocols = [WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2];
21+
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, protocols.ptr, protocols.length);
22+
HINTERNET hConnect = WinHttpConnect(hSession, url.domain.toUTF16z,
23+
INTERNET_DEFAULT_HTTPS_PORT, 0);
24+
scope(exit)
25+
WinHttpCloseHandle(hConnect);
26+
27+
HINTERNET hRequest = WinHttpOpenRequest(hConnect, "GET", url.object.toUTF16z,
28+
null, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES,
29+
WINHTTP_FLAG_SECURE);
30+
31+
if(hRequest is null)
32+
{
33+
import core.sys.windows.winbase;
34+
DWORD code = GetLastError();
35+
string msg;
36+
switch(code)
37+
{
38+
case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE:
39+
msg = `The type of handle supplied is incorrect for this operation.`; break;
40+
case ERROR_WINHTTP_INTERNAL_ERROR:
41+
msg = `An internal error has occurred.`; break;
42+
case ERROR_WINHTTP_INVALID_URL:
43+
msg = `The URL is invalid.`; break;
44+
case ERROR_WINHTTP_OPERATION_CANCELLED:
45+
msg = `The operation was canceled, usually because the handle on which the request was operating was closed before the operation completed.`; break;
46+
case ERROR_WINHTTP_UNRECOGNIZED_SCHEME:
47+
msg = `The URL specified a scheme other than "http:" or "https:".`; break;
48+
case ERROR_NOT_ENOUGH_MEMORY:
49+
msg = `Not enough memory was available to complete the requested operation. (Windows error code)`; break;
50+
default:
51+
wchar* buffer;
52+
DWORD msgLength = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
53+
FORMAT_MESSAGE_IGNORE_INSERTS |
54+
FORMAT_MESSAGE_ALLOCATE_BUFFER, null, code, LANG_NEUTRAL, cast(wchar*)&buffer, 0, null);
55+
if(msgLength)
56+
{
57+
import std.conv:to;
58+
msg = buffer[0..msgLength].to!string;
59+
LocalFree(buffer);
60+
}
61+
break;
62+
}
63+
throw new Exception(msg);
64+
}
65+
66+
scope(exit)
67+
WinHttpCloseHandle(hRequest);
68+
69+
if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
70+
WINHTTP_NO_REQUEST_DATA, 0, 0, 0)
71+
&& WinHttpReceiveResponse(hRequest, null))
72+
{
73+
DWORD remainingDataSize = 0;
74+
75+
do {
76+
if (!WinHttpQueryDataAvailable(hRequest, &remainingDataSize))
77+
break;
78+
if (!remainingDataSize)
79+
break;
80+
81+
DWORD dwRead = 0;
82+
ubyte[] buffer = bufferSink(remainingDataSize);
83+
assert(buffer.length < DWORD.max, "Buffer sink length is too big.");
84+
WinHttpReadData(hRequest, buffer.ptr, cast(DWORD)buffer.length, &dwRead);
85+
if(onDataReceived)
86+
onDataReceived(buffer);
87+
} while (remainingDataSize > 0);
88+
}
89+
90+
return true;
91+
}
92+
93+
ubyte[] downloadToBuffer(string url)
94+
{
95+
ubyte[] buffer;
96+
download(url, (size_t incomingBytes)
97+
{
98+
size_t bufferTail = buffer.length;
99+
buffer.length+= incomingBytes;
100+
return buffer[bufferTail..$];
101+
});
102+
return buffer;
103+
}
104+
105+
void downloadToFile(string url, string targetFile, bool lowMem = false)
106+
{
107+
import std.stdio;
108+
import std.file;
109+
string newFile = targetFile;
110+
if(exists(targetFile))
111+
newFile~= ".temp";
112+
113+
File f = File(newFile, "wb");
114+
if(lowMem)
115+
{
116+
ubyte[4096] buffer;
117+
download(url, (size_t incomingBytes)
118+
{
119+
return incomingBytes > buffer.length ? buffer[0..$] : buffer[0..incomingBytes];
120+
}, (ubyte[] b)
121+
{
122+
f.rawWrite(b);
123+
});
124+
}
125+
else
126+
{
127+
ubyte[] buffer = downloadToBuffer(url);
128+
f.rawWrite(buffer);
129+
}
130+
f.close();
131+
if(newFile != targetFile)
132+
std.file.rename(newFile, targetFile);
133+
}
134+
135+
private struct NetURL
136+
{
137+
string protocol;
138+
string domain;
139+
string object;
140+
141+
this(string url)
142+
{
143+
import std.algorithm.searching;
144+
auto protocolIdx = countUntil(url, "://");
145+
if(protocolIdx != -1)
146+
{
147+
protocol = url[0..protocolIdx+3];
148+
url = url[protocolIdx+3..$];
149+
}
150+
auto objectIdx = countUntil(url, "/");
151+
if(objectIdx == -1)
152+
{
153+
object = "/";
154+
domain = url;
155+
}
156+
else
157+
{
158+
object = url[objectIdx..$];
159+
domain = url[0..objectIdx];
160+
}
161+
162+
}
163+
}

dub.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
"description": "Dub Based Build System, with parallelization per packages and easier to contribute",
44
"authors": ["Hipreme"],
55
"targetPath": "build",
6-
"stringImportPaths": [
7-
"source"
8-
],
6+
"stringImportPaths": ["source"],
97
"configurations": [
108
{
119
"name": "cli",
@@ -42,6 +40,7 @@
4240
"d_dependencies": {"path": "d_dependencies"},
4341
"dub_sdl_to_json": {"path": "dub_sdl_to_json"},
4442
"package_suppliers": {"path": "package_suppliers"},
43+
"d_downloader": {"path": "d_downloader"},
4544
"xxhash3": "~>0.0.5"
4645
}
4746
}

dub.selections.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
"arsd-official": "12.1.0",
88
"colorize": {"path": "colorize"},
99
"d_dependencies": {"path": "d_dependencies"},
10+
"d_downloader": {"path": "d_downloader"},
1011
"dub_sdl_to_json": {"path": "dub_sdl_to_json"},
11-
"sdlite": "1.3.3",
12+
"sdlite": "1.3.4",
1213
"taggedalgebraic": "1.0.1",
1314
"fswatch": "0.6.1",
1415
"package_suppliers": {"path": "package_suppliers"},

package_suppliers/dub.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
],
55
"dependencies": {
66
"hipjson": {"path": "../hipjson"},
7-
"semver": {"path": "../semver"}
7+
"semver": {"path": "../semver"},
8+
"d_downloader": {"path": "../d_downloader"}
89
},
910
"copyright": "Copyright © 2024, Marcelo",
1011
"description": "A minimal D application.",

package_suppliers/source/redub/libs/package_suppliers/dub_registry.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class RegistryPackageSupplier
7777

7878
void loadPackagesMetadata(string[] packages)
7979
{
80-
import std.net.curl;
80+
import d_downloader;
8181
static string getMetadataUrl(string registryUrl, string[] packages)
8282
{
8383
import std.string:join;
@@ -86,7 +86,7 @@ class RegistryPackageSupplier
8686
encodeComponent(`["`~packageName~`"]`)~
8787
"&include_dependencies=true&minimize=true";
8888
}
89-
string data = cast(string)downloadFile(getMetadataUrl(registryUrl, packages));
89+
string data = cast(string)downloadToBuffer(getMetadataUrl(registryUrl, packages));
9090
JSONValue parsed = parseJSON(data);
9191

9292
synchronized(metadataMutex.writer)

0 commit comments

Comments
 (0)