Commit Diff


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)