repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / haikudepot / server / RepositoryDataUpdateProcess.cpp
blob321807576c1625c0c77c480d64de0c3ffcc62b35
1 /*
2 * Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
6 #include "RepositoryDataUpdateProcess.h"
8 #include <stdio.h>
9 #include <sys/stat.h>
10 #include <time.h>
12 #include <FileIO.h>
13 #include <Url.h>
15 #include "ServerSettings.h"
16 #include "StorageUtils.h"
17 #include "DumpExportRepository.h"
18 #include "DumpExportRepositorySource.h"
19 #include "DumpExportRepositoryJsonListener.h"
22 /*! This repository listener (not at the JSON level) is feeding in the
23 repositories as they are parsed and processing them. Processing
24 includes finding the matching depot record and coupling the data
25 from the server with the data about the depot.
28 class DepotMatchingRepositoryListener : public DumpExportRepositoryListener {
29 public:
30 DepotMatchingRepositoryListener(
31 DepotList* depotList);
32 virtual ~DepotMatchingRepositoryListener();
34 virtual void Handle(DumpExportRepository* item);
35 virtual void Complete();
37 private:
38 void NormalizeUrl(BUrl& url) const;
39 bool IsUnassociatedDepotByUrl(
40 const DepotInfo& depotInfo,
41 const BString& urlStr) const;
43 int32 IndexOfUnassociatedDepotByUrl(
44 const BString& url) const;
46 DepotList* fDepotList;
51 DepotMatchingRepositoryListener::DepotMatchingRepositoryListener(
52 DepotList* depotList)
54 fDepotList = depotList;
58 DepotMatchingRepositoryListener::~DepotMatchingRepositoryListener()
63 void
64 DepotMatchingRepositoryListener::NormalizeUrl(BUrl& url) const
66 if (url.Protocol() == "https")
67 url.SetProtocol("http");
69 BString path(url.Path());
71 if (path.EndsWith("/"))
72 url.SetPath(path.Truncate(path.Length() - 1));
76 bool
77 DepotMatchingRepositoryListener::IsUnassociatedDepotByUrl(
78 const DepotInfo& depotInfo, const BString& urlStr) const
80 if (depotInfo.BaseURL().Length() > 0
81 && depotInfo.WebAppRepositorySourceCode().Length() == 0) {
82 BUrl depotInfoBaseUrl(depotInfo.BaseURL());
83 BUrl url(urlStr);
85 NormalizeUrl(depotInfoBaseUrl);
86 NormalizeUrl(url);
88 if (depotInfoBaseUrl == url)
89 return true;
92 return false;
96 int32
97 DepotMatchingRepositoryListener::IndexOfUnassociatedDepotByUrl(
98 const BString& url) const
100 int32 i;
102 for (i = 0; i < fDepotList->CountItems(); i++) {
103 const DepotInfo& depot = fDepotList->ItemAt(i);
105 if (IsUnassociatedDepotByUrl(depot, url))
106 return i;
109 return -1;
113 void
114 DepotMatchingRepositoryListener::Handle(DumpExportRepository* repository)
116 int32 i;
118 for (i = 0; i < repository->CountRepositorySources(); i++) {
119 DumpExportRepositorySource *repositorySource =
120 repository->RepositorySourcesItemAt(i);
121 int32 depotIndex = IndexOfUnassociatedDepotByUrl(
122 *(repositorySource->Url()));
124 if (depotIndex >= 0) {
125 DepotInfo modifiedDepotInfo(fDepotList->ItemAt(depotIndex));
126 modifiedDepotInfo.SetWebAppRepositoryCode(
127 BString(*(repository->Code())));
128 modifiedDepotInfo.SetWebAppRepositorySourceCode(
129 BString(*(repositorySource->Code())));
130 fDepotList->Replace(depotIndex, modifiedDepotInfo);
132 printf("associated depot [%s] with server"
133 " repository source [%s]\n", modifiedDepotInfo.Name().String(),
134 repositorySource->Code()->String());
140 void
141 DepotMatchingRepositoryListener::Complete()
143 int32 i;
145 for (i = 0; i < fDepotList->CountItems(); i++) {
146 const DepotInfo& depot = fDepotList->ItemAt(i);
148 if (depot.WebAppRepositoryCode().Length() == 0) {
149 printf("depot [%s]", depot.Name().String());
151 if (depot.BaseURL().Length() > 0)
152 printf(" (%s)", depot.BaseURL().String());
154 printf(" correlates with no repository in the haiku"
155 "depot server system\n");
161 RepositoryDataUpdateProcess::RepositoryDataUpdateProcess(
162 const BPath& localFilePath,
163 DepotList* depotList)
165 fLocalFilePath = localFilePath;
166 fDepotList = depotList;
170 RepositoryDataUpdateProcess::~RepositoryDataUpdateProcess()
175 status_t
176 RepositoryDataUpdateProcess::Run()
178 printf("will fetch repositories data\n");
180 // TODO: add language ISO code to the path; just 'en' for now.
181 status_t result = DownloadToLocalFile(fLocalFilePath,
182 ServerSettings::CreateFullUrl("/__repository/all-en.json.gz"),
183 0, 0);
185 if (result == B_OK || result == APP_ERR_NOT_MODIFIED) {
186 printf("did fetch repositories data\n");
188 // now load the data in and process it.
190 printf("will process repository data and match to depots\n");
191 result = PopulateDataToDepots();
193 switch (result) {
194 case B_OK:
195 printf("did process repository data and match to depots\n");
196 break;
197 default:
198 MoveDamagedFileAside(fLocalFilePath);
199 break;
202 } else {
203 printf("an error has arisen downloading the repositories' data\n");
206 return result;
210 status_t
211 RepositoryDataUpdateProcess::PopulateDataToDepots()
213 DepotMatchingRepositoryListener* itemListener =
214 new DepotMatchingRepositoryListener(fDepotList);
216 BulkContainerDumpExportRepositoryJsonListener* listener =
217 new BulkContainerDumpExportRepositoryJsonListener(itemListener);
219 status_t result = ParseJsonFromFileWithListener(listener, fLocalFilePath);
221 if (B_OK != result)
222 return result;
224 return listener->ErrorStatus();
228 void
229 RepositoryDataUpdateProcess::GetStandardMetaDataPath(BPath& path) const
231 path.SetTo(fLocalFilePath.Path());
235 void
236 RepositoryDataUpdateProcess::GetStandardMetaDataJsonPath(
237 BString& jsonPath) const
239 jsonPath.SetTo("$.info");
243 const char*
244 RepositoryDataUpdateProcess::LoggingName() const
246 return "repo-data-update";