add staged blob SHA1 to on-disk file index; bump file index version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
diff --git a/lib/fileindex.c b/lib/fileindex.c
index fd6801e..61af730 100644
--- a/lib/fileindex.c
+++ b/lib/fileindex.c
@@ -38,6 +38,7 @@
/* got_fileindex_entry flags */
#define GOT_FILEIDX_F_PATH_LEN 0x00000fff
#define GOT_FILEIDX_F_STAGE 0x0000f000
+#define GOT_FILEIDX_F_STAGE_SHIFT 24
#define GOT_FILEIDX_F_NOT_FLUSHED 0x00010000
#define GOT_FILEIDX_F_NO_BLOB 0x00020000
#define GOT_FILEIDX_F_NO_COMMIT 0x00040000
@@ -159,6 +160,12 @@ got_fileindex_entry_path_len(const struct got_fileindex_entry *ie)
return (size_t)(ie->flags & GOT_FILEIDX_F_PATH_LEN);
}
+uint32_t
+got_fileindex_entry_stage(const struct got_fileindex_entry *ie)
+{
+ return ((ie->flags & GOT_FILEIDX_F_STAGE) >> GOT_FILEIDX_F_STAGE_SHIFT);
+}
+
int
got_fileindex_entry_has_blob(struct got_fileindex_entry *ie)
{
@@ -325,6 +332,7 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_fileindex_entry *ie,
{
const struct got_error *err;
size_t n;
+ uint32_t stage;
err = write_fileindex_val64(ctx, ie->ctime_sec, outfile);
if (err)
@@ -368,7 +376,20 @@ write_fileindex_entry(SHA1_CTX *ctx, struct got_fileindex_entry *ie,
return err;
err = write_fileindex_path(ctx, ie->path, outfile);
- return err;
+ if (err)
+ return err;
+
+ stage = got_fileindex_entry_stage(ie);
+ if (stage == GOT_FILEIDX_STAGE_MODIFY ||
+ stage == GOT_FILEIDX_STAGE_ADD) {
+ SHA1Update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
+ n = fwrite(ie->staged_blob_sha1, 1, SHA1_DIGEST_LENGTH,
+ outfile);
+ if (n != SHA1_DIGEST_LENGTH)
+ return got_ferror(outfile, GOT_ERR_IO);
+ }
+
+ return NULL;
}
const struct got_error *
@@ -496,7 +517,7 @@ read_fileindex_path(char **path, SHA1_CTX *ctx, FILE *infile)
static const struct got_error *
read_fileindex_entry(struct got_fileindex_entry **iep, SHA1_CTX *ctx,
- FILE *infile)
+ FILE *infile, uint32_t version)
{
const struct got_error *err;
struct got_fileindex_entry *ie;
@@ -554,6 +575,26 @@ read_fileindex_entry(struct got_fileindex_entry **iep, SHA1_CTX *ctx,
goto done;
err = read_fileindex_path(&ie->path, ctx, infile);
+ if (err)
+ goto done;
+
+ if (version >= 2) {
+ uint32_t stage = got_fileindex_entry_stage(ie);
+ if (stage == GOT_FILEIDX_STAGE_MODIFY ||
+ stage == GOT_FILEIDX_STAGE_ADD) {
+ n = fread(ie->staged_blob_sha1, 1, SHA1_DIGEST_LENGTH,
+ infile);
+ if (n != SHA1_DIGEST_LENGTH) {
+ err = got_ferror(infile, GOT_ERR_FILEIDX_BAD);
+ goto done;
+ }
+ SHA1Update(ctx, ie->staged_blob_sha1, SHA1_DIGEST_LENGTH);
+ }
+ } else {
+ /* GOT_FILE_INDEX_VERSION 1 does not support staging. */
+ ie->flags &= ~GOT_FILEIDX_F_STAGE;
+ }
+
done:
if (err)
got_fileindex_entry_free(ie);
@@ -605,11 +646,11 @@ got_fileindex_read(struct got_fileindex *fileindex, FILE *infile)
if (hdr.signature != GOT_FILE_INDEX_SIGNATURE)
return got_error(GOT_ERR_FILEIDX_SIG);
- if (hdr.version != GOT_FILE_INDEX_VERSION)
+ if (hdr.version > GOT_FILE_INDEX_VERSION)
return got_error(GOT_ERR_FILEIDX_VER);
for (i = 0; i < hdr.nentries; i++) {
- err = read_fileindex_entry(&ie, &ctx, infile);
+ err = read_fileindex_entry(&ie, &ctx, infile, hdr.version);
if (err)
return err;
err = add_entry(fileindex, ie);
diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
index b66cb0c..33b7f14 100644
--- a/lib/got_lib_fileindex.h
+++ b/lib/got_lib_fileindex.h
@@ -55,6 +55,14 @@ struct got_fileindex_entry {
* Variable length, and NUL-padded to a multiple of 8 on disk.
*/
char *path;
+
+ /*
+ * (since GOT_FILE_INDEX_VERSION 2)
+ * SHA1 of staged blob in repository if stage equals either
+ * GOT_FILEIDX_STAGE_MODIFY or GOT_FILEIDX_STAGE_ADD.
+ * Otherwise, this field is not written to disk.
+ */
+ uint8_t staged_blob_sha1[SHA1_DIGEST_LENGTH];
};
/* Modifications explicitly staged for commit. */
@@ -85,7 +93,7 @@ struct got_fileindex_hdr {
uint32_t signature; /* big-endian */
#define GOT_FILE_INDEX_SIGNATURE 0x676f7449 /* 'g', 'o', 't', 'I' */
uint32_t version; /* big-endian */
-#define GOT_FILE_INDEX_VERSION 1
+#define GOT_FILE_INDEX_VERSION 2
uint32_t nentries; /* big-endian */
/* list of concatenated fileindex entries */
uint8_t sha1[SHA1_DIGEST_LENGTH]; /* checksum of above on-disk data */