aboutsummaryrefslogtreecommitdiff
path: root/src/Package.cpp
blob: c1c00be654e8a6d049dacec2586693c2dd878466 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "../include/Package.hpp"
#include "../include/curl.hpp"
#include "../external/rapidjson/error/en.h"

using namespace std;
using namespace rapidjson;

static Document *packageList = nullptr;

namespace sibs
{
    // TODO: Always downloading is fine right now because the package list is small. This should later be modified to use local cache.
    // The package file should be stored locally (at ~/.sibs/packages.json) and the version file should also be stored.
    // First we check if the version is incorrect and if it, we download the new packages.json file.
    // We should only check if the package list is up to date once every 10 minute or so (make it configurable in a config file?)
    // to improve build performance and reduce server load.
    // Or maybe we dont have to do that at all....
    Result<Document*> Package::getPackageList(const char *url)
    {
        if(packageList)
            return Result<Document*>::Ok(packageList);
        
        HttpResult httpResult = curl::get(url);
        if(!httpResult.success)
            return Result<Document*>::Err(httpResult.str, httpResult.httpCode);
        
        Document *doc = new Document();
        ParseResult parseResult = doc->Parse(httpResult.str.c_str());
        if(!parseResult)
        {
            string errMsg = "Failed to parse package list json file: ";
            errMsg += GetParseError_En(parseResult.Code());
            errMsg += " (";
            errMsg += to_string(parseResult.Offset());
            errMsg += ")";
            return Result<Document*>::Err(errMsg);
        }
        
        packageList = doc;
        return Result<Document*>::Ok(packageList);
    }
    
    Result<string> Package::getPackageUrl(const char *packageName, const char *packageVersion)
    {
        Result<Document*> packageList = Package::getPackageList("https://raw.githubusercontent.com/DEC05EBA/sibs_packages/master/packages.json");
        if(!packageList)
            return Result<string>::Err(packageList);
        
        const Document &packageDoc = *packageList.unwrap();
        const Value &packageMetaData = packageDoc[packageName];
        if(!packageMetaData.IsObject())
        {
            string errMsg = "No package with the name \"";
            errMsg += packageName;
            errMsg += "\" was found";
            return Result<string>::Err(errMsg);
        }
        
        const Value &packageVersions = packageMetaData["versions"];
        if(!packageVersions.IsObject())
        {
            string errMsg = "Package file is corrupt. ";
            errMsg += packageName;
            errMsg += ".versions is not a json object";
            return Result<string>::Err("errMsg");
        }
        
        const Value &package = packageVersions[packageVersion];
        if(!package.IsObject())
        {
            string errMsg = "Package file is corrupt. ";
            errMsg += packageName;
            errMsg += ".versions.";
            errMsg += packageVersion;
            errMsg += " is not a json object";
            return Result<string>::Err(errMsg);
        }
        
        const Value &packageUrlsValue = package["urls"];
        if(!packageUrlsValue.IsArray())
        {
            string errMsg = "Package file is corrupt. ";
            errMsg += packageName;
            errMsg += ".versions.";
            errMsg += packageVersion;
            errMsg += ".urls is not a json array";
            return Result<string>::Err(errMsg);
        }
        
        auto packageUrls = packageUrlsValue.GetArray();
        if(packageUrls.Empty())
        {
            string errMsg = "Package file is corrupt. ";
            errMsg += packageName;
            errMsg += ".versions.";
            errMsg += packageVersion;
            errMsg += ".urls is an empty json array";
            return Result<string>::Err(errMsg);
        }
        
        const Value &packageUrlValue = packageUrls[0];
        if(!packageUrlValue.IsString())
        {
            string errMsg = "Package file is corrupt. ";
            errMsg += packageName;
            errMsg += ".versions.";
            errMsg += packageVersion;
            errMsg += ".urls[0] is not a string";
            return Result<string>::Err(errMsg);
        }
        
        return Result<std::string>::Ok(string(packageUrlValue.GetString(), packageUrlValue.GetStringLength()));
    }
}