|
2 | 2 | #include "object-store.h"
|
3 | 3 | #include "repository.h"
|
4 | 4 | #include "object.h"
|
| 5 | +#include "attr.h" |
5 | 6 | #include "blob.h"
|
6 | 7 | #include "tree.h"
|
7 | 8 | #include "tree-walk.h"
|
@@ -614,17 +615,22 @@ static int fsck_tree(const struct object_id *tree_oid,
|
614 | 615 | ".gitmodules is a symbolic link");
|
615 | 616 | }
|
616 | 617 |
|
| 618 | + if (is_hfs_dotgitattributes(name) || is_ntfs_dotgitattributes(name)) { |
| 619 | + if (!S_ISLNK(mode)) |
| 620 | + oidset_insert(&options->gitattributes_found, |
| 621 | + entry_oid); |
| 622 | + else |
| 623 | + retval += report(options, tree_oid, OBJ_TREE, |
| 624 | + FSCK_MSG_GITATTRIBUTES_SYMLINK, |
| 625 | + ".gitattributes is a symlink"); |
| 626 | + } |
| 627 | + |
617 | 628 | if (S_ISLNK(mode)) {
|
618 | 629 | if (is_hfs_dotgitignore(name) ||
|
619 | 630 | is_ntfs_dotgitignore(name))
|
620 | 631 | retval += report(options, tree_oid, OBJ_TREE,
|
621 | 632 | FSCK_MSG_GITIGNORE_SYMLINK,
|
622 | 633 | ".gitignore is a symlink");
|
623 |
| - if (is_hfs_dotgitattributes(name) || |
624 |
| - is_ntfs_dotgitattributes(name)) |
625 |
| - retval += report(options, tree_oid, OBJ_TREE, |
626 |
| - FSCK_MSG_GITATTRIBUTES_SYMLINK, |
627 |
| - ".gitattributes is a symlink"); |
628 | 634 | if (is_hfs_dotmailmap(name) ||
|
629 | 635 | is_ntfs_dotmailmap(name))
|
630 | 636 | retval += report(options, tree_oid, OBJ_TREE,
|
@@ -1170,38 +1176,70 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
|
1170 | 1176 | static int fsck_blob(const struct object_id *oid, const char *buf,
|
1171 | 1177 | unsigned long size, struct fsck_options *options)
|
1172 | 1178 | {
|
1173 |
| - struct fsck_gitmodules_data data; |
1174 |
| - struct config_options config_opts = { 0 }; |
1175 |
| - |
1176 |
| - if (!oidset_contains(&options->gitmodules_found, oid)) |
1177 |
| - return 0; |
1178 |
| - oidset_insert(&options->gitmodules_done, oid); |
| 1179 | + int ret = 0; |
1179 | 1180 |
|
1180 | 1181 | if (object_on_skiplist(options, oid))
|
1181 | 1182 | return 0;
|
1182 | 1183 |
|
1183 |
| - if (!buf) { |
1184 |
| - /* |
1185 |
| - * A missing buffer here is a sign that the caller found the |
1186 |
| - * blob too gigantic to load into memory. Let's just consider |
1187 |
| - * that an error. |
1188 |
| - */ |
1189 |
| - return report(options, oid, OBJ_BLOB, |
1190 |
| - FSCK_MSG_GITMODULES_LARGE, |
1191 |
| - ".gitmodules too large to parse"); |
| 1184 | + if (oidset_contains(&options->gitmodules_found, oid)) { |
| 1185 | + struct config_options config_opts = { 0 }; |
| 1186 | + struct fsck_gitmodules_data data; |
| 1187 | + |
| 1188 | + oidset_insert(&options->gitmodules_done, oid); |
| 1189 | + |
| 1190 | + if (!buf) { |
| 1191 | + /* |
| 1192 | + * A missing buffer here is a sign that the caller found the |
| 1193 | + * blob too gigantic to load into memory. Let's just consider |
| 1194 | + * that an error. |
| 1195 | + */ |
| 1196 | + return report(options, oid, OBJ_BLOB, |
| 1197 | + FSCK_MSG_GITMODULES_LARGE, |
| 1198 | + ".gitmodules too large to parse"); |
| 1199 | + } |
| 1200 | + |
| 1201 | + data.oid = oid; |
| 1202 | + data.options = options; |
| 1203 | + data.ret = 0; |
| 1204 | + config_opts.error_action = CONFIG_ERROR_SILENT; |
| 1205 | + if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB, |
| 1206 | + ".gitmodules", buf, size, &data, &config_opts)) |
| 1207 | + data.ret |= report(options, oid, OBJ_BLOB, |
| 1208 | + FSCK_MSG_GITMODULES_PARSE, |
| 1209 | + "could not parse gitmodules blob"); |
| 1210 | + ret |= data.ret; |
1192 | 1211 | }
|
1193 | 1212 |
|
1194 |
| - data.oid = oid; |
1195 |
| - data.options = options; |
1196 |
| - data.ret = 0; |
1197 |
| - config_opts.error_action = CONFIG_ERROR_SILENT; |
1198 |
| - if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB, |
1199 |
| - ".gitmodules", buf, size, &data, &config_opts)) |
1200 |
| - data.ret |= report(options, oid, OBJ_BLOB, |
1201 |
| - FSCK_MSG_GITMODULES_PARSE, |
1202 |
| - "could not parse gitmodules blob"); |
1203 |
| - |
1204 |
| - return data.ret; |
| 1213 | + if (oidset_contains(&options->gitattributes_found, oid)) { |
| 1214 | + const char *ptr; |
| 1215 | + |
| 1216 | + oidset_insert(&options->gitattributes_done, oid); |
| 1217 | + |
| 1218 | + if (!buf || size > ATTR_MAX_FILE_SIZE) { |
| 1219 | + /* |
| 1220 | + * A missing buffer here is a sign that the caller found the |
| 1221 | + * blob too gigantic to load into memory. Let's just consider |
| 1222 | + * that an error. |
| 1223 | + */ |
| 1224 | + return report(options, oid, OBJ_BLOB, |
| 1225 | + FSCK_MSG_GITATTRIBUTES_LARGE, |
| 1226 | + ".gitattributes too large to parse"); |
| 1227 | + } |
| 1228 | + |
| 1229 | + for (ptr = buf; *ptr; ) { |
| 1230 | + const char *eol = strchrnul(ptr, '\n'); |
| 1231 | + if (eol - ptr >= ATTR_MAX_LINE_LENGTH) { |
| 1232 | + ret |= report(options, oid, OBJ_BLOB, |
| 1233 | + FSCK_MSG_GITATTRIBUTES_LINE_LENGTH, |
| 1234 | + ".gitattributes has too long lines to parse"); |
| 1235 | + break; |
| 1236 | + } |
| 1237 | + |
| 1238 | + ptr = *eol ? eol + 1 : eol; |
| 1239 | + } |
| 1240 | + } |
| 1241 | + |
| 1242 | + return ret; |
1205 | 1243 | }
|
1206 | 1244 |
|
1207 | 1245 | int fsck_object(struct object *obj, void *data, unsigned long size,
|
@@ -1240,45 +1278,58 @@ int fsck_error_function(struct fsck_options *o,
|
1240 | 1278 | return 1;
|
1241 | 1279 | }
|
1242 | 1280 |
|
1243 |
| -int fsck_finish(struct fsck_options *options) |
| 1281 | +static int fsck_blobs(struct oidset *blobs_found, struct oidset *blobs_done, |
| 1282 | + enum fsck_msg_id msg_missing, enum fsck_msg_id msg_type, |
| 1283 | + struct fsck_options *options, const char *blob_type) |
1244 | 1284 | {
|
1245 | 1285 | int ret = 0;
|
1246 | 1286 | struct oidset_iter iter;
|
1247 | 1287 | const struct object_id *oid;
|
1248 | 1288 |
|
1249 |
| - oidset_iter_init(&options->gitmodules_found, &iter); |
| 1289 | + oidset_iter_init(blobs_found, &iter); |
1250 | 1290 | while ((oid = oidset_iter_next(&iter))) {
|
1251 | 1291 | enum object_type type;
|
1252 | 1292 | unsigned long size;
|
1253 | 1293 | char *buf;
|
1254 | 1294 |
|
1255 |
| - if (oidset_contains(&options->gitmodules_done, oid)) |
| 1295 | + if (oidset_contains(blobs_done, oid)) |
1256 | 1296 | continue;
|
1257 | 1297 |
|
1258 | 1298 | buf = read_object_file(oid, &type, &size);
|
1259 | 1299 | if (!buf) {
|
1260 | 1300 | if (is_promisor_object(oid))
|
1261 | 1301 | continue;
|
1262 | 1302 | ret |= report(options,
|
1263 |
| - oid, OBJ_BLOB, |
1264 |
| - FSCK_MSG_GITMODULES_MISSING, |
1265 |
| - "unable to read .gitmodules blob"); |
| 1303 | + oid, OBJ_BLOB, msg_missing, |
| 1304 | + "unable to read %s blob", blob_type); |
1266 | 1305 | continue;
|
1267 | 1306 | }
|
1268 | 1307 |
|
1269 | 1308 | if (type == OBJ_BLOB)
|
1270 | 1309 | ret |= fsck_blob(oid, buf, size, options);
|
1271 | 1310 | else
|
1272 |
| - ret |= report(options, |
1273 |
| - oid, type, |
1274 |
| - FSCK_MSG_GITMODULES_BLOB, |
1275 |
| - "non-blob found at .gitmodules"); |
| 1311 | + ret |= report(options, oid, type, msg_type, |
| 1312 | + "non-blob found at %s", blob_type); |
1276 | 1313 | free(buf);
|
1277 | 1314 | }
|
1278 | 1315 |
|
| 1316 | + oidset_clear(blobs_found); |
| 1317 | + oidset_clear(blobs_done); |
| 1318 | + |
| 1319 | + return ret; |
| 1320 | +} |
| 1321 | + |
| 1322 | +int fsck_finish(struct fsck_options *options) |
| 1323 | +{ |
| 1324 | + int ret = 0; |
| 1325 | + |
| 1326 | + ret |= fsck_blobs(&options->gitmodules_found, &options->gitmodules_done, |
| 1327 | + FSCK_MSG_GITMODULES_MISSING, FSCK_MSG_GITMODULES_BLOB, |
| 1328 | + options, ".gitmodules"); |
| 1329 | + ret |= fsck_blobs(&options->gitattributes_found, &options->gitattributes_done, |
| 1330 | + FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB, |
| 1331 | + options, ".gitattributes"); |
1279 | 1332 |
|
1280 |
| - oidset_clear(&options->gitmodules_found); |
1281 |
| - oidset_clear(&options->gitmodules_done); |
1282 | 1333 | return ret;
|
1283 | 1334 | }
|
1284 | 1335 |
|
|
0 commit comments