commit 515140783dfbb42d9deb4c8edd7d251d9cdf362c from: Stefan Sperling date: Tue Dec 25 15:18:05 2018 UTC preparation for idempotent checkout: read exisiting file index commit - a143fb78680e46194d8a68b0fcd96b57d164a6d0 commit + 515140783dfbb42d9deb4c8edd7d251d9cdf362c blob - a6bdde165134042c5baf59120676cb60d8c8d153 blob + 0eda1d0481edfd72a67595b0c94a5025155c779a --- lib/fileindex.c +++ lib/fileindex.c @@ -28,16 +28,40 @@ #include "got_lib_fileindex.h" const struct got_error * -got_fileindex_entry_alloc(struct got_fileindex_entry **entry, - const char *ondisk_path, const char *relpath, uint8_t *blob_sha1, - uint8_t *commit_sha1) +got_fileindex_entry_update(struct got_fileindex_entry *entry, + const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1) { struct stat sb; - size_t len; if (lstat(ondisk_path, &sb) != 0) return got_error_from_errno(); + entry->ctime_sec = sb.st_ctime; + entry->ctime_nsec = sb.st_ctimensec; + entry->mtime_sec = sb.st_mtime; + entry->mtime_nsec = sb.st_mtimensec; + entry->uid = sb.st_uid; + entry->gid = sb.st_gid; + entry->size = (sb.st_size & 0xffffffff); + if (sb.st_mode & S_IFLNK) + entry->mode = GOT_INDEX_ENTRY_MODE_SYMLINK; + else + entry->mode = GOT_INDEX_ENTRY_MODE_REGULAR_FILE; + entry->mode |= ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) << + GOT_INDEX_ENTRY_MODE_PERMS_SHIFT); + memcpy(entry->blob_sha1, blob_sha1, SHA1_DIGEST_LENGTH); + memcpy(entry->commit_sha1, commit_sha1, SHA1_DIGEST_LENGTH); + + return NULL; +} + +const struct got_error * +got_fileindex_entry_alloc(struct got_fileindex_entry **entry, + const char *ondisk_path, const char *relpath, uint8_t *blob_sha1, + uint8_t *commit_sha1) +{ + size_t len; + *entry = calloc(1, sizeof(**entry)); if (*entry == NULL) return got_error_from_errno(); @@ -49,28 +73,14 @@ got_fileindex_entry_alloc(struct got_fileindex_entry * *entry = NULL; return err; } - - (*entry)->ctime_sec = sb.st_ctime; - (*entry)->ctime_nsec = sb.st_ctimensec; - (*entry)->mtime_sec = sb.st_mtime; - (*entry)->mtime_nsec = sb.st_mtimensec; - (*entry)->uid = sb.st_uid; - (*entry)->gid = sb.st_gid; - (*entry)->size = (sb.st_size & 0xffffffff); - if (sb.st_mode & S_IFLNK) - (*entry)->mode = GOT_INDEX_ENTRY_MODE_SYMLINK; - else - (*entry)->mode = GOT_INDEX_ENTRY_MODE_REGULAR_FILE; - (*entry)->mode |= ((sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) << - GOT_INDEX_ENTRY_MODE_PERMS_SHIFT); - memcpy((*entry)->blob_sha1, blob_sha1, SHA1_DIGEST_LENGTH); - memcpy((*entry)->commit_sha1, commit_sha1, SHA1_DIGEST_LENGTH); + len = strlen(relpath); if (len > GOT_INDEX_ENTRY_F_PATH_LEN) len = GOT_INDEX_ENTRY_F_PATH_LEN; (*entry)->flags |= len; - return NULL; + return got_fileindex_entry_update(*entry, ondisk_path, blob_sha1, + commit_sha1); } void @@ -90,6 +100,18 @@ got_fileindex_entry_add(struct got_fileindex *fileinde return NULL; } +struct got_fileindex_entry * +got_fileindex_entry_get(struct got_fileindex *fileindex, const char *path) +{ + struct got_fileindex_entry *entry; + TAILQ_FOREACH(entry, &fileindex->entries, entry) { + if (strcmp(entry->path, path) == 0) + return entry; + } + + return NULL; +} + struct got_fileindex * got_fileindex_alloc(void) { @@ -428,8 +450,11 @@ got_fileindex_read(struct got_fileindex *fileindex, FI SHA1Init(&ctx); n = fread(buf, 1, len, infile); - if (n != len) + if (n != len) { + if (n == 0) /* EOF */ + return NULL; return got_ferror(infile, GOT_ERR_IO); + } SHA1Update(&ctx, buf, len); blob - e8716e82b5c7226df522570f9907830e40f4274d blob + 78770a187a8aeab06554502e2672852c6e8e833b --- lib/got_lib_fileindex.h +++ lib/got_lib_fileindex.h @@ -85,6 +85,8 @@ struct got_fileindex_hdr { uint8_t sha1[SHA1_DIGEST_LENGTH]; /* checksum of above on-disk data */ }; +const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *, + const char *, uint8_t *, uint8_t *); const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **, const char *, const char *, uint8_t *, uint8_t *); void got_fileindex_entry_free(struct got_fileindex_entry *); @@ -93,4 +95,6 @@ void got_fileindex_free(struct got_fileindex *); const struct got_error *got_fileindex_write(struct got_fileindex *, FILE *); const struct got_error *got_fileindex_entry_add(struct got_fileindex *, struct got_fileindex_entry *); +struct got_fileindex_entry *got_fileindex_entry_get(struct got_fileindex *, + const char *); const struct got_error *got_fileindex_read(struct got_fileindex *, FILE *); blob - 65f2e530842a66c066ddafb9f0879a4bc0f8c9f5 blob + f6afe827f9a74a99f9dc08df62881efabab7310d --- lib/worktree.c +++ lib/worktree.c @@ -463,13 +463,19 @@ add_file_on_disk(struct got_worktree *worktree, struct fsync(fd); - err = got_fileindex_entry_alloc(&entry, ondisk_path, - apply_path_prefix(worktree, path), blob->id.sha1, - worktree->base_commit_id->sha1); - if (err) - goto done; - - err = got_fileindex_entry_add(fileindex, entry); + entry = got_fileindex_entry_get(fileindex, + apply_path_prefix(worktree, path)); + if (entry) + err = got_fileindex_entry_update(entry, ondisk_path, + blob->id.sha1, worktree->base_commit_id->sha1); + else { + err = got_fileindex_entry_alloc(&entry, ondisk_path, + apply_path_prefix(worktree, path), blob->id.sha1, + worktree->base_commit_id->sha1); + if (err) + goto done; + err = got_fileindex_entry_add(fileindex, entry); + } if (err) goto done; done: @@ -635,7 +641,7 @@ got_worktree_checkout_files(struct got_worktree *workt struct got_tree_object *tree = NULL; char *fileindex_path = NULL, *new_fileindex_path = NULL; struct got_fileindex *fileindex = NULL; - FILE *new_index = NULL; + FILE *index = NULL, *new_index = NULL; err = lock_worktree(worktree, LOCK_EX); if (err) @@ -654,6 +660,21 @@ got_worktree_checkout_files(struct got_worktree *workt goto done; } + /* + * Read the file index. + * Checking out files is supposed to be an idempotent operation. + * If the on-disk file index is incomplete we will try to complete it. + */ + index = fopen(fileindex_path, "rb"); + if (index == NULL) { + err = got_error_from_errno(); + goto done; + } + err = got_fileindex_read(fileindex, index); + fclose(index); + if (err) + goto done; + err = got_opentemp_named(&new_fileindex_path, &new_index, fileindex_path); if (err)