| 123 | } |
| 124 | |
| 125 | [[nodiscard]] inline Result packageMetadataMatches(const Download& download, const Package& package, bool& matches) |
| 126 | { |
| 127 | matches = false; |
| 128 | if (download.isGitClone) |
| 129 | { |
| 130 | matches = true; |
| 131 | return Result(true); |
| 132 | } |
| 133 | |
| 134 | FileSystem fs; |
| 135 | SC_TRY(fs.init(".")); |
| 136 | if (not fs.existsAndIsFile(package.packageLocalTxt.view())) |
| 137 | { |
| 138 | return Result(true); |
| 139 | } |
| 140 | |
| 141 | String metadata; |
| 142 | SC_TRY(readFileIntoString(package.packageLocalTxt.view(), metadata)); |
| 143 | StringView metadataView = metadata.view(); |
| 144 | |
| 145 | // Old sidecars are MD5-only and should trigger a fresh install. |
| 146 | if (metadataView.containsString("SC_PACKAGE_MD5=")) |
| 147 | { |
| 148 | return Result(true); |
| 149 | } |
| 150 | |
| 151 | StringView urlValue; |
| 152 | StringView hashValue; |
| 153 | StringViewTokenizer lines(metadataView); |
| 154 | while (lines.tokenizeNextLine()) |
| 155 | { |
| 156 | StringView line = lines.component.trimWhiteSpaces(); |
| 157 | if (line.startsWith("SC_PACKAGE_URL=")) |
| 158 | { |
| 159 | SC_TRY(line.splitAfter("SC_PACKAGE_URL=", urlValue)); |
| 160 | } |
| 161 | else if (line.startsWith("SC_PACKAGE_HASH=")) |
| 162 | { |
| 163 | SC_TRY(line.splitAfter("SC_PACKAGE_HASH=", hashValue)); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | if (urlValue != download.url.view()) |
| 168 | { |
| 169 | return Result(true); |
| 170 | } |
| 171 | |
| 172 | if (download.expectedHash.isEmpty()) |
| 173 | { |
| 174 | matches = hashValue.isEmpty(); |
| 175 | return Result(true); |
| 176 | } |
| 177 | |
| 178 | SmallString<80> expectedMetadataHash; |
| 179 | auto builder = StringBuilder::create(expectedMetadataHash); |
| 180 | SC_TRY(builder.append("{}:{}", packageHashName(download.hashType), download.expectedHash.view())); |
| 181 | builder.finalize(); |
| 182 | matches = hashValue == expectedMetadataHash.view(); |
no test coverage detected