commit f61329c0eec5e9caf6953aa2709a47e9462e65fa from: Stefan Sperling via: Thomas Adam date: Fri Jan 24 22:02:34 2025 UTC skip full content comparison in 'got status' if file sizes differ Speeds up 'got status' in work trees that contain large files which are modified. This change exposes bugs in 'got revert' which now manifest as test failures. One bug where the size recorded in the file index is not updated during revert, and another where a wrong base commit is recorded in the file index entry during revert. Fix those bugs, too. ok jamsek commit - b14eda0ab0630951b6e93297e6fe5370f0db98e3 commit + f61329c0eec5e9caf6953aa2709a47e9462e65fa blob - 5fcb85e30f8a1fb9563edec2537e6d9f22ae35f9 blob + 60ed4f1275e1e8cd94f11d6722c110d4d3bd391b --- lib/worktree.c +++ lib/worktree.c @@ -1836,8 +1836,22 @@ get_file_status(unsigned char *status, struct stat *sb goto done; } fd = -1; + + if (staged_status == GOT_STATUS_NO_CHANGE && + S_ISREG(sb->st_mode) && + got_fileindex_entry_filetype_get(ie) == + GOT_FILEIDX_MODE_REGULAR_FILE && + ie->size != (sb->st_size & 0xffffffff)) { + /* + * The size of regular files differs. We can skip the full + * content comparison loop below but still need to check + * for conflict markers. + */ + *status = GOT_STATUS_MODIFY; + } + hdrlen = got_object_blob_get_hdrlen(blob); - for (;;) { + while (*status == GOT_STATUS_NO_CHANGE) { const uint8_t *bbuf = got_object_blob_get_read_buf(blob); err = got_object_blob_read_block(&blen, blob); if (err) @@ -5352,6 +5366,11 @@ revert_file(void *arg, unsigned char status, unsigned goto done; } } + err = got_fileindex_entry_update(ie, + a->worktree->root_fd, relpath, + &blob->id, &ie->commit, 0); + if (err) + goto done; } else { int is_bad_symlink = 0; if (te && S_ISLNK(te->mode)) { @@ -5369,14 +5388,11 @@ revert_file(void *arg, unsigned char status, unsigned } if (err) goto done; - if (status == GOT_STATUS_DELETE || - status == GOT_STATUS_MODE_CHANGE) { - err = got_fileindex_entry_update(ie, - a->worktree->root_fd, relpath, - &blob->id, a->worktree->base_commit_id, 1); - if (err) - goto done; - } + err = got_fileindex_entry_update(ie, + a->worktree->root_fd, relpath, + &blob->id, &ie->commit, 0); + if (err) + goto done; if (is_bad_symlink) { got_fileindex_entry_filetype_set(ie, GOT_FILEIDX_MODE_BAD_SYMLINK);